一、一维数组
1. 变量名指向地址
2. 数组新建和输入
3. 数组可以先声明后分配
这种情况的话实际上是先new了一个指针a,a此时指向null,后面再将a指向new int[3]分配的空间
4. 静态初始化
5. 数组使用的一些注意细节
6. 值传递和引用传递的区别
其实不管是基本数据类型还是引用类型,拷贝的时候都是从栈中直接赋值变量名指向的东西过去,区别就在于n1指向的是数而arr1指向的是地址
7. 数组拷贝
8. 数组的扩容
二、 二维数组
1. 动态初始化
2. 内存存在形式
3. java数组可以列数不确定,列数可以不一样
遍历的时候才真正开空间
4. 静态初始化
5. 二维数组的注意细节
6. 对数组声明和初始化的理解练习
三、面对对象基础篇
1. 内存中对象的存在形式
2. 成员变量的注意细节
ps:基本数据类型和引用类型
基本数据类型就这几种,其他的都是引用类型
注意 p1只是 对象名,new出来的空间才是真正的对象
就比如小明和李明都是这个人的名字而已,并不是他自己
3. 创建对象的方法
先声明对象cat,此时cat指向null,等new cat的时候,在堆中创建空间,然后将该空间的地址比如OX1122赋值给cat,cat就指向了OX1122的这个空间,即指向了这个对象。
4. 类和对象的内存分配机制
执行第一行代码
执行第二行代码
执行第三行代码
(必须注意,有数据就一定有地址空间,将“小明”这个字符串的地址回填)
执行第四行代码(要是前面对老师说的内存分配机制理解够好的话,这里自己也能推出来)
5. java内存结构分析
练习:分析以下代码会出现怎样的结果
(b指向null,可是a并没有,a仍然指向该对象,只要该对象还有指向它的,就不会被回收)
6. 成员方法的调用机制
只要调用一个方法就会产生一个新的栈
返回之后这个栈(名字不是真的叫gersum栈,只是为了理解方便)就会被销毁,就是这个空间被释放了/回收了/没有了。将得到的值(res)返回赋值给调用它的地方。
当main方法也结束了之后,main栈空间也被回收
ps:java在什么情况下发生自动类型转换
7. 成员方法传参机制(基本数据类型)
这两个栈是独立的,而且传递的参数是基本数据类型,在swap中形参的改变不影响实参。
8. 成员方法传参机制(引用数据类型)
9. 怎么判断对象是不是同一个
- 可以通过输出对象的hashcode看看对象是否是同一个
- 通过对象比较 if(p1==p2)
四、递归
1. 简单的递归分析
2. 递归重要规则
3. 汉诺塔代码
五、一些知识点
1. 方法重载
返回类型相同与否都没关系,关键是f选项中的参数列表是一样的。所以不能构成方法重载,这样是方法重新定义了,会报错。
2. 可变参数
注意细节
可以直接传数组进去
3. 作用域
结合jvm内存机制理解,say方法用的时候会在栈中创建,用完之后就销毁该方法占用的空间了,其内的变量也就自然而然没了。
4. 构造方法/构造器
注意这里,构造器不是创建一个对象,而是在创建了一个对象之后,对对象的属性进行初始化,比如填值。
每次的new XX()其实都会调用默认无参构造器
反编译发现确实会有这样的构造器
如果没有显式定义无参构造器,只有有参的构造器,当你new Dog()的时候立刻报错,因为原先的无参构造器已经被覆盖掉了,要是你还想用,就需要定义出来。
5. 对象创建的流程分析
在这里实际上属性被三次初始化了,第一次是建造对象时,默认初始化age=0,name=null;第二次是成员变量显式定义初始化,age=90,name=null;第三次是使用构造器,name=“小倩”,age=20。
这里还要再次强调,p是对象的引用,也可以说是对象名,但它不是对象,真正的对象在堆里面。
6. this关键字
1) 引入
这样的话实际上属性并没有被赋值,所以需要this
2) this关键字的jvm内存理解(this本质)
3) 小结
关于第四点
7. 包
8. 访问修饰符
六、 封装
七、 继承
1. 关系图
2. 注意细节
在子类初始化的时候默认调用super(),只不过是隐式的,没让我们看见而已
3. 继承内存布局
那当我想访问name的时候,访问到的是哪个呢?
答:从后往前找,有这个属性并且可以访问的话就返回。
如果遇到一个属性能找到,但是它是私有的,直接报错,不再往上找。
4. 练习
在这里,B类无参构造器因为有this所以没有super,但是它的有参构造器是有super的。
5. super关键字
属性和方法的规则一样
6. 方法重写/覆盖
八、多态
1. 介绍
2. 注意细节
1)向上转型
重点:属性(成员变量)看编译类型,成员方法看运行类型!!!!!!!!!!
2)向下转型
注意 这里父类引用必须指向的是当前目标类型的对象,即Animal animal=new Cat(),animal本来在内存中就是指向一个Cat对象的!
3)属性的值
4)instanceOf
3. 一些练习
第五个容易错哦,注意规则是:
属性看编译类型(等号左边),方法看运行类型(等号右边)。
4. java的动态绑定机制
1) 问题引入
如果这样的话,大家都能理解答案是为什么。
但是如果我现在去掉子类的sum方法,它自然就会想要往父类去找sum方法,而父类的sum方法里面要调用getI()方法,那么父类调用getI方法是父类的还是子类的呢?
2) 定义
由于规则1,上面引入问题的答案就应该是,它会去调用子类的getI方法!!结果a.sum()=30。
那如果这次又去掉子类的sum1方法呢?
由于规则2,现在调用到的sum1是父类的方法,而属性又没有动态绑定机制,所以i是父类的i,答案就是20。
那现在如果又没有了子类的i,a.sum()会返回什么?
根据上面的分析,调用a.sum的时候它会去调用父类的sum方法,父类又由于动态绑定机制规则1会去调用子类的getI方法,而子类的getI方法想要调用属性i,但是现在子类B中并没有i这个成员变量,它就又往上去查找,找到父类的i,所以答案是20。
5. 多态数组
具体可以看自己的代码
(D:\Project\JavaBasic\src\main\java\com\XXX\polymorphicArray)
如果想要调用每个类的特有方法
6. 多态参数
九、Object类详解
1. equals()
1)equals和==的区别
2)如何重写equals
首先,如果不重写,我们在比较的时候,由于本类没有equals方法,它去找父类,Person没有继承其他父类,那就只能找到Object,而Object的equals源码只是比较两个对象是否一样,即内存地址是否一样,那自然不一样,返回false。
所以我们就需要去重写Object的equals方法。
基本数据类型判断的是值是否相等,==是比较运算符,也是运算的一种,不同数据类型运算时,先转成精度最大的一种比较,byte short char先转成int再做运算。
2. hashcode()
3. toString()
全类名就是包名+类名
4. finalize
5. 断点调试