摘抄别人的一句话:要想理解反射的原理,首先要了解什么是类型信息。Java让我们在运行时识别对象和类的信息,主要有2种方式:一种是传统的RTTI,它假定我们在编译时已经知道了所有的类型信息;另一种是反射机制,它允许我们在运行时发现和使用类的信息
一.RTTI
为理解RTTI在Java里如何工作,首先必须了解类型信息在运行期是如何表示的。这时要用到一个名为“Class对象”的特殊形式的对象,其中包含了与类有关的信息(有时也把它叫作“元类”)。事实上,我们要用Class对象创建属于某个类的全部“常规”或“普通”对象。RTTI在java里表现为3种形式:
- 经典造型,即下溯造型,造型失败产生一个ClassCastException违例
- 代表对象类型的Class对象。可查询Class对象,获取有用的运行期资料
- instanceof,它会返回一个布尔值
第一种和第三种忽略,主要是第二种。
关于Class类
每一个class都有一个Class对象,可以理解为类对象,有且仅有一个。在运行期,一旦我们需要new一个class的对象时,JVM首先会去检查这个class是否已经载入,如果没有载入,JVM会去查同名的.class文件,并将其载入,载入时便会生成一个Class对象,它保存了这个class的相关信息,静态变量也是在类载入的时候初始化。在java1.0种,使用Class实现RTTI有3种形式:
- Class.forName(“类名”);
- 类型.class;
- 对象.getClass();
3种形式得到的都是一个class的Class对象,第二种相较第一种要更安全和快捷,因为第二种在编译器会进行检查,并且没有调用方法,但就实用性而言我觉得第一种较为常用。
二.反射
在java1.1种,Class类得到了扩展,我们可以从一个Class对象种获取这个class类型的成员信息,但要注意的一点是:获取的信息是Class对象的,并不是某个具体的class对象的信息,因此我们要用某些信息的时候都要与一个具体的class对象相绑定。
1.通过反射获取构造方法并使用
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class Test
{
public static void main(String[] args)
{
try {
Class clazz=Class.forName("Student");
//Constructor[] constructors=clazz.getConstructors();获取所有公有的构造方法
//Constructor[] constructors=clazz.getDeclaredConstructors();//获取所有的构造方法
Constructor con=clazz.getConstructor(String.class);//获取公有的参数类型为String的构造方法,注意参数为对应类型Class对象!!
Student st=(Student) con.newInstance("老李");//用构造方法生成一个Student对象
System.out.println(st.name);
con=clazz.getDeclaredConstructor(String.class,int.class);//获取构造方法种参数为String和int的方法,这儿获取的私有构造方法
con.setAccessible(true);//将私有构造的访问权限设为true,否则无法用构造方法创建对象
st =(Student) con.newInstance("小李",7991);
System.out.println(st.name+" "+st.ID);
}catch (Exception e){
e.printStackTrace();
}
}
}
class Student
{
String name;
public int ID;
public Student(String name)
{
this.name=name;
}
public Student()
{
this.name="老张";
}
private Student(String name,int id)
{
this.name=name;
this.ID=id;
}
public void print()
{
System.out.println("name="+name+",ID="+ID);
}
private void add(int num){ID+=num;}
private void change(String name){this.name=name;}
}
输出如下:
2.通过反射获取成员变量并使用
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class Test
{
public static void main(String[] args)
{
Student student=new Student("老李");
student.ID=7881;
try {
Class clazz=Class.forName("Student");
//Field[] fields=clazz.getFields();获取公有的成员变量
//Field[] fields=clazz.getDeclaredFields();获取所有的成员变量
Field name=clazz.getDeclaredField("name");//获取name变量
Field id=clazz.getDeclaredField("ID");//获取ID变量
name.set(student,"老张");
id.set(student,5000);
System.out.println(student.name+" "+student.ID);
}catch (Exception e){
e.printStackTrace();
}
}
}
class Student
{
String name;
public int ID;
public Student(String name)
{
this.name=name;
}
public Student()
{
this.name="老张";
}
private Student(String name,int id)
{
this.name=name;
this.ID=id;
}
public void print()
{
System.out.println("name="+name+",ID="+ID);
}
private void add(int num){ID+=num;}
private void change(String name){this.name=name;}
}
输出如下:
3.通过反射获取方法并使用
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test
{
public static void main(String[] args)
{
Student student=new Student();
try {
Class clazz=Class.forName("Student");
//Method[] methods=clazz.getMethods();获取公有的方法
//Method[] methods=clazz.getDeclaredMethods();获取所有的方法
Method me=clazz.getMethod("print");//获取print方法
me.invoke(student);//调用student对象的print方法
me=clazz.getDeclaredMethod("add",int.class);//获取add方法
me.setAccessible(true);//设置访问权限为true;
me.invoke(student,50);//调用student对象的add方法
student.print();
me=clazz.getDeclaredMethod("down");
me.invoke(null);//调用静态方法不需要对象,静态成员同理
}catch (Exception e){
e.printStackTrace();
}
}
}
class Student
{
String name;
public int ID;
public Student(String name)
{
this.name=name;
}
public Student()
{
this.name="老张";
}
private Student(String name,int id)
{
this.name=name;
this.ID=id;
}
public void print()
{
System.out.println("name="+name+",ID="+ID);
}
private void add(int num){ID+=num;}
private void change(String name){this.name=name;}
public static void down(){System.out.println("调用静态方法");}
}
输出如下:
推荐一篇关于反射的博客:https://blog.csdn.net/sinat_38259539/article/details/71799078