基本概念

成员与初始化

  • 对象是数据行为的集合(主观能动性)
  • 一切使用new运算符创造出来的都是对象
    • new Object()
    • 特例 new Integer() \ new String() \ new Object[]
  • 所有对象都在内存堆上被分配
  • 每个对象都包含自己的数据(成员变量)
    • 原生类型的成员,保存于对象开辟的内存空间中
    • 引用类型的成员,再对象开辟的内存空间中保存了一个地址
  • 新建对象的过程是
    • 再堆上分配空间
    • 执行必要的初始化工作,成员赋默认值
    • 执行构造器函数,如果没有构造器,编译器自动生成一个
  • 其他概念

    • 字符串存放于常量池
    • 方法存放于metaspace元空间

      方法的重载overload

  • 重载overload与重写\覆盖(overide)是不同的

  • 重载可以使用相同的方法名,但参数表类型不同(仅仅返回值不同是不行的)
  • 当遇到类型自动装箱问题,最匹配的的优先(方法重载的顺序),如果多个类型匹配优先级相同,会有歧义bug(取决于继承树顺序)
  • null 没有类型,发生匹配歧义时,需要对null先进行强制类型转换

    1. public class Main {
    2. public static void main(String[] args) {
    3. // 实际调用的方法是print(HashMap)
    4. print((HashMap)null);
    5. }
    6. public static void print(int i) {
    7. System.out.println("I'm int!");
    8. }
    9. public static void print(Integer i) {
    10. System.out.println("I'm Integer!");
    11. }
    12. public static void print(Number i) {
    13. System.out.println("I'm Number!");
    14. }
    15. public static void print(Object i) {
    16. System.out.println("I'm Object!");
    17. }
    18. public static void print(HashMap i) {
    19. System.out.println("I'm HashMap!");
    20. }
    21. }
  • 仅仅返回值不同是不能重载的,因为java允许忽略返回值对函数进行调用,此时会产生歧义(但这种情况在jvm中是合法的)

  • 方法参数的默认值常需要重载实现,比如在void返回值类型的函数中调用其他参数类型的同名函数,此时提供指定参数值,如下段构造器默认值的实现方案,HashMap API也使用此方式
    1. public class Cat {
    2. int age;
    3. String name;
    4. // 创建一只默认的猫,1岁,名为张三
    5. public Cat(){
    6. this("张三"); // 调用第二个构造器
    7. }
    8. // 创建一只默认的猫,1岁,名为name
    9. public Cat(String name){
    10. this(1,name);// 调用第三个构造器
    11. }
    12. // 创建一只有age和name的猫
    13. public Cat(int age,String name){
    14. this.age = age;
    15. this.name = name;
    16. }
    17. }

    对象的初始化顺序

  1. 划分内存空间
  2. 必要的初始化工作顺序
    1. 静态成员的初始化
    2. 静态初始化块
    3. 成员的初始化
    4. 初始化块
  3. 执行构造器函数

    1. public class Cat {
    2. // 静态部分,不属于任何对象,执行顺序在main函数的调用前面(对main函数分析完就先执行了,main函数栈帧还未被压栈)
    3. // 最先执行的是类的静态部分
    4. static int a = 123;
    5. static {
    6. }
    7. // 成员部分
    8. int age = 1;
    9. String name = "张三";
    10. {
    11. for(int i = 0; i<5; i++){
    12. age += i;
    13. }
    14. }
    15. public Cat(int age,String name){
    16. this.age = age;
    17. this.name = name;
    18. }
    19. public static void main(String[] args){
    20. new Cat(2,"ABC");
    21. }
    22. }

    对象的生命周期

  • jvm通过GC roots沿引用链可达的对象都是活对象,其他被判断没有被引用的对象被执行垃圾回收机制对其进行回收
  • 没有被引用的对象,jvm的GC(Garbage Collection会结合内存压力等情况自动判断是否对其回收
  • 一直创建对象可能引起爆内存Exception in thread “main” java.lang.OutOfMemoryError: Java heap space

    1. public class Main {
    2. public static void main(String[] args) {
    3. // 请想办法在这里写一些代码,占用尽可能多的内存,令JVM抛出内存不足的OutOfMemoryError异常
    4. Object[] array = new Object[10000];
    5. for (int i = 0; i < 10000; i++) {
    6. array[i] = new byte[1024 * 1024];
    7. }
    8. }
    9. }
  • GC回收时机

    • Allocation Failure 在堆内存中分配时,如果因为可用剩余空间不足导致对象内存分配失败,这时系统会触发一次GC
    • System.gc() 在应用层,Java开发工程师可以主动调用此API来请求一次GC