- 前言
- 1. JDK/JRE/JVM区别
- 2. 构造方法
- 3. 重载
- 4. 面向对象
- 4.1 封装
- 4.2 继承
- 4.3 多态
- 5. 关键字
- 5.1 static
- 5.2 final
- 6. 抽象类
- 7. 接口
- 8. object类
- 9. String/StringBuilder/StringBuffer
- 10. 自动装箱和自动拆箱
主要针对之前汇总的四篇文章笔记
更加细致化的重点
用于面试的泛泛而谈
java 零基础学习
jvm包括jdk,jdk包括jre
jdk适合编写的时候,jre适合编译的时候
- JRE:java运行环境
- JDK:Java开发工具箱
- JVM:java虚拟机
JVM的内存结构中三块比较重要的内存空间
- 方法区:存储代码片段,存储xxx.class字节码文件,类加载器将代码加载到这
- 堆内存:面向对象
- 栈内存:所需要的内存空间(局部变量)
调用构造方法来完成对象的创建,以及对象属性的初始化 *** 作
一个类中可以定义多个构造方法,这些构造方法构成方法重载
一个类中定义多个同名的方法,但要求每个方法具有不同的参数的类型或参数的个数
和返回值类型(void/int)无关,和修饰符列表(public static)无关
面向对象具有三大特征
- 封装
- 继承
- 多态
- 属性私有化(使用private关键字进行修饰。)
- 对外提供简单的 *** 作入口
(1个属性对外提供两个set和get方法。外部程序只能通过set方法修改,只能通过get方法读取,可以在set方法中设立关卡来保证数据的安全性)
- 有了继承之后才会衍生出方法的覆盖和多态机制
- java 中的继承只支持单继承,不支持多继承,但支持间接继承,例如:class C extends B,class B extends A。C++中支持多继承
- 子类继承父类,除构造方法和被 private 修饰的数据不能继承外,剩下都可以继承
执行顺序:
先调用父类的静态代码块,子类静态代码块
在执行父类的代码以及构造函数从上往下,最后执行子类的代码块和构造函数
多态存在的三个必要条件
- 继承
- 方法覆盖
- 父类型引用指向子类型对象
5. 关键字 5.1 static对于多态的理解一定要分为编译阶段和运行阶段来进行分析,编译阶段只是看父类型中是否存在要调用的方法,如果父类中不存在,则编译器会报错,编译阶段和具体 new 的对象无关。但是在运行阶段就要看底层具体 new的是哪个类型的子对象了,new的这个子类型对象可以看做“真实对象”,自然在运行阶段就会调用真实对象的相关方法。例如代码:Animal a = new Cat(); a.move();,在编译阶段编译器只能检测到a的类型是Animal,所以一定会去Animal类中找move()方法,如果 Animal 中没有 move()方法,则编译器会报错,即使 Cat 中有 move()方法,也会报错,因为编译器只知道 a 的类型是 Animal 类,只有在运行的时候,实际创建的真实对象是 Cat,那么在运行的时候就会自动调用 Cat 对象的 move()方法。这样就可以达到多种形态,也就是说编译阶段一种形态,运行阶段的时候是另一种形态
-
java语言中凡是用 static 修饰的都是类相关的,不需要创建对象,直接通过“类名”即可访问,即使使用“引用”去访问,在运行的时候也和堆内存当中的对象无关
-
实例变量必须先创建对象,通过“引用”去访问,而静态变量访问时不需要创建对象,直接通过“类名”访问。实例变量存储在堆内存当中,静态变量存储在方法区当中。实例变量在构造方法执行过程中初始化,静态变量在类加载时初始化
-
当一个类的所有对象的某个“属性值”不会随着对象的改变而变化的时候,建议将该属性定义为静态属性(或者说把这个变量定义为静态变量),静态变量在类加载的时候初始化,存储在方法区当中,不需要创建对象,直接通过“类名”来访问
this 和 super 都是无法使用在静态方法当中的,必须适用对象创建
定义的东西都不能修改,类方法变量,如下
- final 修饰的类不能被继承
- final 修饰的方法不能被覆盖
- final 修饰的变量不能被修改
如果修饰的引用,那么这个引用只能指向一个对象,也就是说这个引用不能再次赋值,即地址已经确定了不能修改,但被指向的对象(属性值)是可以修改的
final的对象是实例变量,放在堆中,会占用空间,可以结合static,节省空间,放在常量(常量和静态变量都存在方法区,都在类加载的时候初始化)
6. 抽象类抽象方法不能被 final 修饰,因为抽象方法就是被子类实现的
- 抽象的方法只需在抽象类中,提供声明,不需要实现
- 如果一个类中含有抽象方法,那么这个类必须定义成抽象类。抽象类中不一定有抽象方法,抽象方法必须出现在抽象类中
一个非抽象的类,继承抽象类,必须将抽象类中的抽象方法进行覆盖/重写/实现
7. 接口类与类是继承extends,类与接口是实现implements,其实都是继承
- 完全抽象的,支持多继承,且一个接口可以继承多个接口
- 所有的元素都是public修饰的,抽象方法的public abstract可以省略,常量的public static final可以省略,方法不能有方法体
当一个非抽象的类实现接口的话,必须将接口中所有的抽象方法全部实现(覆盖、重写)
抽象类和接口的区别:
-
抽象类是半抽象的,有构造方法,只允许出现常量和抽象方法。类和类之间只能单继承,一个抽象类只能继承一个类(单继承)。
-
接口是完全抽象的,没有构造方法,接口和接口之间支持多继承,一个类可以同时实现多个接口
protected Object clone() // 负责对象克隆的。
int hashCode() // 获取对象哈希值的一个方法。
boolean equals(Object obj) // 判断两个对象是否相等
String toString() // 将对象转换成字符串形式
protected void finalize() // 垃圾回收器负责调用的方法
String为什么是不可变的:源代码String类中有一个byte[]数组,这个byte[]数组采用了final修饰,因为数组一旦创建长度不可变。并且被final修饰的引用一旦指向某个对象之后,不可再指向其它对象,所以String是不可变的!“abc” 无法变成 “abcd”
- StringBuffer中的方法都有:synchronized关键字修饰。表示StringBuffer在多线程环境下运行是安全的。
- StringBuilder中的方法都没有:synchronized关键字修饰,表StringBuilder在多线程环境下运行是不安全的。
10. 自动装箱和自动拆箱源代码StringBuffer/StringBuilder内部实际上是一个byte[]数组, 这个byte[]数组没有被final修饰,StringBuffer/StringBuilder的初始化容量我记得应该是16,当存满之后会进行扩容,底层调用了数组拷贝的方System.arraycopy()…是这样扩容的。所以StringBuilder/StringBuffer适合于使用字符串的频繁拼接 *** 作
- 自动装箱:基本数据类型自动转换成包装类。
- 自动拆箱:包装类自动转换成基本数据类型。
补充:
java中为了提高程序的执行效率,将[-128到127]之间所有的包装对象提前创建好,放到了一个方法区的“整数型常量池”当中了,目的是只要用这个区间的数据不需要再new了,直接从整数型常量池当中取出来
所以
Integer a = 128; Integer b = 128; System.out.println(a == b); //false Integer x = 127; Integer y = 127; // == 永远判断的都是两个对象的内存地址是否相同。 System.out.println(x == y); //true
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)