1、初始化数据块
当创建对象或加载类时运行的代码。有两种类型:
静态初始化器:加载类时运行的代码,static{ }括号之间的代码被称为静态初始化器。它只在第一次加载类时运行。静态初始化器中只能访问类的静态变量。即使创建三个类的实例,也只会运行一次static块。静态代码块只能访问在静态代码块之前的变量,在它之后的变量,在前面的静态代码块中可以赋值,但是
不可以访问。//报错:cannot reference a field before it is defined
实例初始化器:创建新对象时运行的代码,即{ }括号之间的代码每次创建类的实例时,代码块都会运行。静态变量和非静态变量都能在代码块中被访问
2、类的初始化顺序
1)先执行static语句块和static语句(如 static A a = new A(),即使类中有main方法,也要先执行static的内容。),静态初始化只会在首次加载class对象时进行一次。如果有父类,则先加载父类的static对象和static代码块。再加载子类的static对象和static代码块。
2)先加载父类的成员变量和构造函数。调用父类的构造器,从最高级的父类,一层层向下。如B是A的子类,C是B的子类,则new C()时会先调用A的构造器,然后是B的构造器。。。
3)执行所有出现在字段定义处的初始化动作。即在调用D类的构造器之前,会先完成1,2,3这三句话的操作。
4)调用构造代码块。
5)调用子类的构造器主体
3、java创建对象的几种方式:
1)用new语句创建对象
2)用反射,newInstace()方法
3)调用对象的clone()方法
4)运用反序列化手段,调用java.io.ObjectInputStream对象的readObject()方法
1和2会明确的显示调用构造函数,3是在内存上对已有对象的影印所以不会调用构造函数,4是从文件中还原类的对象,也不会调用构造函数。
4、深浅克隆
使用clone方法的条件:1、实现cloneable接口。2、用public修饰符重新定义clone方法。
先看student和professor类:前者拥有后者的引用。后者是正常代码。
可以看到,当类的字段不是基本数据类型时,就会出问题,克隆动作后,s1的导师信息被改成了和s2的导师信息完全一致。这就是浅克隆。为了避免这种情况,就要改写professor的代码,让引用类型也实现克隆的接口
同时要改写student代码
最后结果就没问题了,是想要的结果
BeanUtils.copyProperties(source, target); 是浅拷贝
5、static方法为什么不能调用非static方法?
非static方法要和对象关联在一起,必须创建一个对象后,才可以在该对象上进行方法调用,static方法的调用不需要创建对象。所以当一个static方法被调用时,可能还没有创建任何实例对象,所以无法调用非static方法
6、static方法可以访问static变量,不能访问正常变量。非static方法可以访问static变量,也能访问正常变量
7、抽象类和接口的不同:
前者:可以有抽象方法,普通方法,自己的数据成员。被继承时,如果有抽象方法没被重写,子类也是抽象类。抽象类实现接口时,可以不用实现接口的所有抽象方法(未被实现的抽象方法也被继承了只是没有实现)。如果再有普通类继承该抽象类,必须实现剩余的未被实现的抽象方法。抽象类可以实现接口,抽象类中可以有静态的main方法。
后者:只有抽象方法(public修饰的),常量(static final),可以有静态方法(static而不是abstract static),必须是有方法体的。被实现时,所有方法必须被重写。接口的修饰符只可以是abstract和public。接口可以继承多个接口。接口中可以有静态的main方法
8、接口可以继承多个接口,类不能多继承是因为如果两个父类都有相同的方法,子类不知道该继承哪一个。而接口中的方法都是抽象的,所以无所谓
9、反射机制
是指在运行状态中,对于任意一个类,都能获取这个类的所有属性和方法,对于任意一个对象,都能调用它的任何一个方法和属性,这种动态获取信息以及动态调用对象方法的功能成为反射机制
1)虚拟机在class文件的加载阶段,把类信息保存在方法区中,并在java堆中生成一个class对象(就是类对象),作为类信息的入口
获取class对象有三种方式:
a. 通过实例变量.getClass()方法
b. 通过类名方式Dog.class,这种方式只会加载Dog类,并不触发其类构造器的初始化。
c. 通过Class.forName(String classname)方式,classname是全路径名,包名+类名。
Class.forName("com.kuaishou.zt.card.domain.user.spi.ShapeFactory")
JDK源码实现中,forName方法会调用Native方法forName0(),在jvm中调用findClassFromClassLoader()加载Dog类,其原理和ClassLoader一样,将会触发Dog类的类构造器初始化,forName()声明如下
其中initialize参数,用来告诉虚拟机是否需要对加载的类初始化,如果此参数是false,则不会进行初始化Dog类
2)获取类字段
getFields()获得public的属性,getDeclaredFields()获取所有属性
getFields(“sex”)获取public属性,getDeclaredFields(“age”)可以获取私有属性
3)获取类方法
与类字段类似,分别获取public方法和全部方法,getMethod()中传入的参数为方法名称,参数类型,textMethod(String str)参数是String,所以要传入String.class。如果该方法没有参数,则传入null
4)获取相应的实例构造器,并生成类实例。与获取类字段的方式类似,可以分别获取public构造器和全部构造器
如果构造函数中参数是String,则getConstructor()要传入String.class
5)获取类的其他信息
6)反射操作对象
a、使用Class对象的newInstance()方法创建该对象的实例,这种方法要求改Class对象有默认构造器,而newInstance()方法实际上是利用默认构造器来创建该类的实例
b、先使用Class对象获取指定的Constructor对象,再调用Constructor对象的newInstace()方法来创建Class对象对应类的实例,这种方法可以选择使用指定的构造器来创建实例。注意要传入String.class, Integer.class, String.class
7)调用方法
先创建对象的实例,然后通过Class对象获取指定的方法,getMethod(String name)参数为String,所以在getMethod()中要传入String.class。注意invoke()方法返回的是Object,必要时要进行类型转换
8) 访问私有属性
要用setAccessible()设置访问权值,age是private属性,setInt中要传入类的实例,getInt也要传入类的实例
标签:调用,java,String,对象,基础,static,方法,class From: https://www.cnblogs.com/MarkLeeBYR/p/17113169.html