继承中的类加载 -- 理论掌握
类加载动作是发生在我们程序代码执行之前,但是在代码中有一个东西是和类加载息息相关的 --- 类当中staic修饰的内容。
其中特别是静态代码块,里面的代码是在加载期被执行的,所以我们需要知道静态代码块在继承关系下,所体现出来的特性。
需要大家掌握的结论:
1、当程序当中需要用到哪个类的时候,就会加载哪个类,也就会执行它的静态代码块; 用谁就加载谁,而不是写了谁就加载谁;
2、如果加载一个子类,那么会自动加载它的父类。因为子类代码中明确告知了有一部分共有属性和行为没有定义在子类本身身上,而是继承于父类。如果不加载父类,这部分共有的子类信息就会丢失掉。
加载的顺序:先父类,再子类。
3、一个类只加载一次!
如果父类已经被加载过了,那么加载子类的时候不会再去加载它。
4、现在的Java虚拟机在加载的时候采用的是JIT(just in time) --- 即时加载
其含义就是,它不是预先把要用到的类进行加载,全部完成以后才开始执行;而是边执行边加载,用到谁就加载谁。
顺口提的你们需要知道缩写: JDK JRE JVM GC JIT IDE(不是IDEA) OO OOA OOD OOP
this 和 super -- 开发中比较常用 面试也常出现
this 关键字
this有两种用法: “this.” 和 “this()”
1、当作为"this."的时候,this的含义指代的是当前对象,口语化就是指"我";
我们用它主要是用来访问当前对象的属性和行为。这其中既包括的有定义在本类当中的属性和行为,
也包括从父类继承的属性和行为。
用“this.”访问本类定义的内容,没有任何问题,都可以看;
访问父类定义的内容,要受父类中该内容声明的访问修饰符的限制。
2、this()的作用是在本类的一个构造方法当中,调用本类的另一个构造方法,达到构造方法当中代码
能够共享。
特点:
1、this()只能写在构造方法里面,且只能写在第一句;
2、this()是根据实参与形参匹配去寻找到底调用的是本类中的哪一个其他构造;
3、不能够使用this()在构造方法当中形成“递归”
4、this() 只负责共享被调用构造方法里面的代码,而不会重新创建新对象。
super关键字
super也有两种用法:"super." 和 “super()”
1、当作为“super.”的时候,super的含义指代的是当前对象的父类对象部分,口语化指的是“我身上来自于父亲的那部分”
用"super."访问本类定义的内容,全部看不到;因为这些内容都是存在于子类特有部分的,而super看的从父类继承过来的那部分。
访问父类定义的内容,能看到但同样要受父类中该内容声明的访问修饰符的限制。
总结:“this.”能看到的,"super."不一定能看到;"super."能看到的,"this."一定能看到。因此,我们更多的时候使用的是"this."。
有一种情况,我们会使用"super."
如果子类重写了父类的某个方法,然后我们在子类中又想去调用这个方法在父类里面的实现,那么这个时候要用"super."。如果用"this.",你就在调用重写后的实现了。
2、super()的作用是在子类的构造方法里面,指定调用父类的某一个构造方法。
特点:
1、子类的构造方法里面就算一句代码都没有写,编译器也会自动加一个super(),用来默认调用父类的公共无参构造;
2、super()也是根据实参与形参的匹配去寻找到底调用的是父类的哪一个构造;
3、super()只能写在构造方法里面,也只能写在构造方法的第一句; 这说明一个构造方法里面this() 与 super() 不能共存,只能写一个。
根类:Object -- 非常重要,这是唯一一个里面所有方法都要求Java程序员掌握的类
在Java当中,有一个非常特殊的类 -- Object,它的地位很特殊。它是所有类的根类(包括数组),它是祖宗!!! 任何一个类,如果我们没有主动写继承,那么就会让它默认继承Object这个类。作为一个祖宗类,根据类的继承层次结构,它里面定义的属性和方法,会被子子孙孙无条件的继承下去。
Object 既然是所有类的 根类,那么它的方法一定会被所有类拥有。在这个层面上讲,Object里面方法一定都是共用性最强的方法,是Java认为只要你是一个对象你就该有的方法。
这些方法有:
equals --- 判断两个对象是否相等
toString --- 返回对象的字符串描述
hashcode --- 返回哈西值 --- 留到学习集合框架的时候讲
getClass --- 获取类模版对象 --- 留到反射的时候讲
clone --- 克隆 --- 留到设计模式,“原型模式”的时候讲
notify --- 唤醒线程 --- 留到线程的时候讲
notifyAll --- 唤醒所有线程 --- 留到线程的时候讲
wait --- 让线程等待 --- 留到线程的时候讲
finalize --- 对象的销毁方法
equals 方法
当我们在比较两个对象是否相等的时候,我们一直以来都有一个运算符可以做这件事情。这个运算符就是所谓的"=="。
这个“==”,我们长期使用,前面也讲过。基本数据类型的变量可以用来比较两个变量里面的值是否相等;
而引用数据类型的变量,用它比较的时候,是比较两个引用是否相等。什么是引用是否相等?说白了就是这两个变量里面的引用有没有指向同一个对象,指向同一个得到true,没有指向同一个得到false。
但是还有一种更常见的情况,那就是我们要判断是两个对象里面的内容是否相等。这种情况下,"=="是无能为力的了。所以,这就是equals方法要做的事情:判断两个对象内容是否相等。
equals()方法设计出来就是让程序员去重写的。因为,在当年写Object的时候,并不知道后续的程序员会书写什么样的子类(也就是说对子类的内容一无所知),所以他们只能规范:
1、所有的对象都有可能会有相互比较内容的情况发生,为了不让后续程序员各自发挥起各种各样的方法名,他们定义了一个专用的方法去规范;
2、由于不知道要具体后续程序员要如何比?这个比较规则是由具体业务确定的,所以他们暂时先写一个用"=="号比较的实现,以后交给子类的程序员去重写。
equals方法的使用:
1、什么时候用?如果我们需要判断本类的两个对象是否相等(内容相等或是业务相等),而不是指向同一个对象。那么我们不用自己去创建方法,而是重写来自于Object的equals方法。
2、怎么用?当然就是在这个类中重写这个方法,然后把需要实现的逻辑在它的方法体里面实现。
3、如果没有重写equals,那么Object当中的实现是"=="号。
toString方法
先解除一个误会,很多初学者会误以为这个方法的作用是:把一个对象转换成字符串。其实不是,而是返回这个对象的字符串描述。
toString方法的使用:
1、它是做什么的? 当我们对一个类的对象进行字符串操作的时候(直接打印一个对象,或直接拼接一个对象),那么JVM会自动调用该对象的toString(),把返回的字符串作为这个对象的描述信息进行使用。
2、咋用? 重写!把你需要看到的信息在该方法的实现内部进行拼接就可以了。
3、如果没有重写该方法,那么它的效果是: 类的限定名@对象的hash值
这里解释一下hash值:hash值是JVM根据hash算法,得到的每个对象在内存存放位置的唯一标识。 它不是内存地址,Java为了程序安全不会把内存地址公布给我们,你们可以想象成用了hash函数对这个值做了一次加密。这个hash值往往是用16进制的方式展示出来的