1.Java反射机制是在运行状态中,对于任意一个类(class文件),都能够知道该类的所有属性和方法。
(1)对于任意一个对象,都能够调用它的任一方法和属性。
(2)java语言的反射机制:动态获取信息及动态调用对象。也可以理解为对类的解剖。
2.为什么要出现反射机制,它的优势在哪里?
(1)反射机制可以动态的调用对象及动态的获取对象的属性和方法,可以极大的提高程序的扩展性。试想反射机制出现之前,扩展程序功能的主要方式就是继承与多态,但是每次继承与多态的实现,都需要对代码进行重写,这对于已经完成的应用来说几乎是不可能做到的。而反射机制仅仅需要修改其配置文件即可完成同样的工作。这就是反射机制的优势。
(2)反射机制的工作需要帮助文档的参与,因为获取类的属性和功能需要预先知道该类提供了哪些数据及方法。
3.反射机制的工作原理
一旦应用程序使用反射机制,就需要为该应用提供配置文件,应用程序运行时读取相应的配置文件,从配置文件中获取所需要的类名等相关信息。然后通过相应的方法获取到该类的对象。通过对象获取该类的数据及相应的方法,进而对该类进行操作,实现相应的功能。
4.Java完全面相对象的特点:
在java语言中,任何数据都是以对象的形式存在的。最简单的代码就是一个公共类,任何类都直接或者间接的继承了Object类。对象,基本数据类型,引用数据类型都是以对象的方式存在的。这就为反射机制的存在提供了可能。
5.类Class的作用:
由于Java面向对象的特点,想要对一个类进行完全的解剖,首先就需要获取该类的字节码文件,就可以使用Class类获取字节码文件中的所有内容,而反射也就是依靠该类来完成的。下面就讲解具体的使用方式。
6.获取字节码文件对象的方式:
不足:使用这种方法,必须首先创建该类的对象,由该对象调用父类中的方法getClass()来获取相应的字节码。不过该类对象已经存在,获取字节码文件已经没有意义,并且书写麻烦。
(2)任何数据类型都具备静态属性class,可以通过该属性来获取类的字节码文件。
不足:该方法简单,但是还是要明确使用到类中的静态成员,即在程序中明确使用的类名,该方法扩展性不足。
(2)创建带参的对象
创建带参的对象过程如下:思路与空参创建方法基本相同,只不过需要首先获取带参的对象构造器即可。
需要注意:构造器的访问权限是default,而getConstructor只能获取字节码文件中的公共类,故必须使用getDeclaredConstructor才能获取字节码文件中的构造器。
(1)对于任意一个对象,都能够调用它的任一方法和属性。
(2)java语言的反射机制:动态获取信息及动态调用对象。也可以理解为对类的解剖。
2.为什么要出现反射机制,它的优势在哪里?
(1)反射机制可以动态的调用对象及动态的获取对象的属性和方法,可以极大的提高程序的扩展性。试想反射机制出现之前,扩展程序功能的主要方式就是继承与多态,但是每次继承与多态的实现,都需要对代码进行重写,这对于已经完成的应用来说几乎是不可能做到的。而反射机制仅仅需要修改其配置文件即可完成同样的工作。这就是反射机制的优势。
(2)反射机制的工作需要帮助文档的参与,因为获取类的属性和功能需要预先知道该类提供了哪些数据及方法。
3.反射机制的工作原理
一旦应用程序使用反射机制,就需要为该应用提供配置文件,应用程序运行时读取相应的配置文件,从配置文件中获取所需要的类名等相关信息。然后通过相应的方法获取到该类的对象。通过对象获取该类的数据及相应的方法,进而对该类进行操作,实现相应的功能。
4.Java完全面相对象的特点:
在java语言中,任何数据都是以对象的形式存在的。最简单的代码就是一个公共类,任何类都直接或者间接的继承了Object类。对象,基本数据类型,引用数据类型都是以对象的方式存在的。这就为反射机制的存在提供了可能。
5.类Class的作用:
由于Java面向对象的特点,想要对一个类进行完全的解剖,首先就需要获取该类的字节码文件,就可以使用Class类获取字节码文件中的所有内容,而反射也就是依靠该类来完成的。下面就讲解具体的使用方式。
6.获取字节码文件对象的方式:
事例Person类:
class Person
{
private int age;
private String name;
Person(){
System.out.println("Person run");
}
Person(String name,int age){
this.name = name;
this.age = age;
System.out.println("Person run + name ::"+name +" age :"+age);
}
public void show(){
System.out.println("Person name :"+name +" age :"+age);
}
public void set(String name,int age){
this.name = name;
this.age = age;
System.out.println("Person set run");
}
}
(1)由于任何类都直接或间接的继承了Object类,故可以使用Object类中的方法getClass()来获取相应类的字节码文件对象。
public static void getClassObject_1(){
Person p = new Person();
Class clazz = p.getClass();
System.out.println("结果:" + clazz);
}
结果:
---------- java ----------
Person run
结果:class Person
不足:使用这种方法,必须首先创建该类的对象,由该对象调用父类中的方法getClass()来获取相应的字节码。不过该类对象已经存在,获取字节码文件已经没有意义,并且书写麻烦。
(2)任何数据类型都具备静态属性class,可以通过该属性来获取类的字节码文件。
public static void getClassObject_2(){
Class clazz = Person.class;
System.out.println("结果:" + clazz);
}
---------- java ----------
结果:class Person
不足:该方法简单,但是还是要明确使用到类中的静态成员,即在程序中明确使用的类名,该方法扩展性不足。
(3)使用类Class中的forName()方法,只要给定类的字符串名就可以获取类的字节码文件。该方法更为扩展,可以通过字符串进行随意的更改。
需要注意的是:
(1)使用forName()方法需要抛出访问异常ClassNotFoundException。
(2)若类包含在包中,则字符串需要包含包名。
public static void getClassObject_3() throws ClassNotFoundException {
String className = "Person";
Class clazz = Class.forName(className);
System.out.println("结果:" + clazz);
}
---------- java ----------
结果:class Person
优势:该方法只要有名称即可,更为方便,扩展性更高。
7.新的创建对象的方式:
(1)旧的方式:
以前创建对象都是使用new关键字。过程为:现根据被new的类的名字找寻该类的字节码文件并将该文件加载进内存,并创建该字节码文件对象。然后创建该字节码文件所对应的类的对象。
(2)新的方式:新的方式看起来很麻烦,实际应用中会发现这种方式的可扩展性和复用性极高。
首先通过字符串找到该类名称,通过名称找到对应的字节码文件,将字节码文件加载进内存产生对应的Class对象。通过Class对象的成员方法创建对应的类的对象。
以Person类为例,创建对象过程如下:
(1)创建空参的对象
/*注:为书写方便,本人直接抛出Exception。*/
public static void creatNewObject_1() throws Exception{
String className = "Person";
Class clazz = Class.forName(className);
Object obj = clazz.newInstance();
System.out.println("对象创建结果:" + obj);
}
---------- java ----------
Person run
对象创建结果:Person@1db9742
(2)创建带参的对象
创建带参的对象过程如下:思路与空参创建方法基本相同,只不过需要首先获取带参的对象构造器即可。
需要注意:构造器的访问权限是default,而getConstructor只能获取字节码文件中的公共类,故必须使用getDeclaredConstructor才能获取字节码文件中的构造器。
public static void creatNewObject_2() throws Exception{
String className = "Person";
Class clazz = Class.forName(className);
@SuppressWarnings("unchecked")
//Constructor constructor = clazz.getConstructor(String.class,int.class);
Constructor constructor = clazz.getDeclaredConstructor(String.class,int.class);
Object obj = constructor.newInstance("小米",50);
((Person)obj).show();
}