01 类加载顺序
package com. rjxy. testAbstract;
public class Animal {
public String test = "AnimalFeild" ;
public static String testStatic = "AnimalStaticFeild" ;
public Animal ( ) {
System. out. println ( "我是animal中的无参数构造方法" ) ;
}
{
System. out. println ( "我是animal中的普通程序块" + this . test) ;
}
static {
testStatic ( ) ;
System. out. println ( "我是animal中的静态代码块" + testStatic) ;
}
public void test ( ) {
System. out. println ( "我是animal中的普通方法" ) ;
}
public static void testStatic ( ) {
System. out. println ( "我是animal类中静态方法" ) ;
}
}
package com. rjxy. testAbstract;
public class Person extends Animal {
public String test = "PersonFeild" ;
public static String testStatic = "PersonStaticFeild" ;
public Person ( ) {
System. out. println ( "我是Person中的无参数构造方法" ) ;
}
{
System. out. println ( "我是Person中的普通程序块" + this . test) ;
}
static {
testStatic ( ) ;
System. out. println ( "我是Person中的静态代码块" + testStatic) ;
}
public void test ( ) {
System. out. println ( "我是Person中的普通方法" ) ;
}
public static void testStatic ( ) {
System. out. println ( "我是Person类中静态方法" ) ;
}
}
package com. rjxy. testAbstract;
import org. junit. jupiter. api. Test;
public class Application {
@Test
public void test ( ) {
Person p = new Person ( ) ;
}
}
运行结果: 解释 分配空间 :当JVM进程启动,向OS索要内存空间。OS给它分配一定的内存空间后,JVM再给自己的各个区分配内存空间,如堆区、方法区、栈区。 加载顺序 : 先由bootstrap类加载器加载必要的类,如java.lang包下的类。应用类加载器加载Application,之后初始化,从main方法入口进入,执行到new Person()时,JVM发现这个是主动使用。所以就要加载、初始化这个Person类,但有父才能有子, 所以必须先加载、初始化它的父类。因此父类Animal的Class文件率先被加载到方法区中,在堆中也会产生一个描述该Class文件的对象。然后就是加再子类的过程。加载完这两个类进行初始化,父类先被初始化,所以①②先被输出。子类再被初始化,所以③④被输出。 注意:为类变量分配内存是在链接的准备阶段完成的,在方法区中,每个Class类模板都有其对应的静态空间,用以保存静态变量、静态方法、静态块 new 关键字真正开始执行。先在堆中分配内存空间,之后加载父类非静态成员(属性、方法、块、构造方法依次)。执行块代码,执行构造方法代码。同样的,加载子类非静态成员,执行子类块,执行子类构造方法。 最后将栈中的引用执行堆中。
02 抽象类和接口的区别
类成员 属性:正常类属性能有的,抽象类属性也能有 方法:一般方法也可以有。抽象方法不能用private修饰,因为这样不能被子类继承。因为抽象类本身的意义就在于对具体类的抽象,最终是要被继承的。缺省情况下为public,通过eclipse可看出。 块:一般的、静态的都存在 构造方法:可以存在,但不能在main中 new,原因是抽象类中可能存在未实现的方法 。之所以存在构造方法,是因为子类再new的过程会调用父类的构造方法,所以存在是必要的 抽象类特性 可以单继承抽象类、具体类。具体类继承抽象类的话,要么实现其抽象方法,要么声明为抽象类。通过对抽象类类成员的分析,抽象类除了多了一个抽象方法外,其他的与一般类无异。抽象类可以没有抽象成员,也可以全是抽象成员。
类成员 属性:不能含有一般属性,只能是public static final,可以不写,但换成其他会报错 方法:不能含有一般方法,只能是public abstract,可以不写,但不能换成其他 块:不能有,块本身就是没有修饰符、返回值的特殊方法,是具体的 构造方法:没有。因为在属性是静态常量、方法没有方法体,块也没有,这些东西直接保存在方法区就好。堆中创建对象是无意义的,接口不能创建对象。 接口特性 接口不能继承别的类 抽象类可以多实现接口,抽象列实现接口的情况比如Servlet接口和GenericServlet的关系。 具体类可以多实现接口 接口多继承接口