您的位置:首页 > 编程语言 > Java开发

java反射

2016-04-10 15:01 483 查看
Java Reflection
Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法

反射相关的主要API:
java.lang.Class:代表一个类
java.lang.reflect.Method:代表类的方法
java.lang.reflect.Field:代表类的成员变量
java.lang.reflect.Constructor:代表类的构造方

Class 类:
在Object类中定义了以下的方法,此方法将被所有子类继承: public final Class getClass()
Class 类的常用方法:



实例:

import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class TestReflection {
//有了反射,可以通过反射创建一个类的对象,并调用其中的属性、方法

public void test3(){
Person p=new Person();
Class cla=p.getClass();//通过运行时类的对象,调用其getClass方法,返回其运行时类
System.out.println(cla);
}

public void test2() throws Exception{
Class cla=Person.class;

//1.创建cla对应的运行时类Person类的对象
Person p=(Person)cla.newInstance();
System.out.println(p);

//2.通过反射调用运行时类的指定的属性
//2.1
Field f1=cla.getField("name");
f1.set(p, "LiMing");
System.out.println(p);
//2.2
Field f2=cla.getDeclaredField("age");
f2.setAccessible(true);
f2.set(p, 20);
System.out.println(p);

//3.通过反射调用运行时类的指定的方法
Method m1=cla.getMethod("show");
m1.invoke(p);

Method m2=cla.getMethod("display", String.class);
m2.invoke(p, "China");
}

//不使用反射的情况下,创建一个对象,并调用其中的属性、方法
public void test1(){
Person person=new Person();
person.setName("LiMing");
person.setAge(20);
person.show();
person.display("HK");
}
}
public class Person {
private String name;
private int age;
public Person(){
super();
}
public Person(String name){
super();
this.name=name;
}
public Person(String name,int age){
super();
this.name=name;
this.age=age;
}

public void setName(String name){
this.name=name;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age=age;
}
public int getAge(){
return age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public void show(){
System.out.println("我是一个人!");
}
public void display(String nation){
System.out.println("我的国籍是:"+nation);
}
}


java.lang.Class:是反射的源头
我们创建了一个类,通过编译(javac.exe)生成相应的.class文件。之后我们使用java.exe加载(JVM的类加载器)此.class文件,此.class文件加载到内存以后,就是一个运行时类,存在缓冲区,那么这个运行时类本身就是一个Class实例。
1.一个运行时类只加载一次。
2.有了Class类的实例以后,我们才可以进行如下的操作:
1)创建对应的运行时类的对象
2)获取对应的运行时类的完整结构(属性、方法、构造器、内部类、父类、所在的包、异常、注解...)
3)调用对应的运行时类的指定的结构(属性、方法、构造器)
4)反射的应用:动态代理

实例化Class类对象(四种方法):
1.若已知具体的类,通过类的class属性获取,该方法 最为安全可靠,程序性能最高
实例:Class clazz = String.class;
2.已知某个类的实例,调用该实例的getClass()方法获取Class对象
实例:Class clazz = “www.atguigu.com”.getClass();
3.已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取,可能抛出ClassNotFoundException
实例:Class clazz = Class.forName(“java.lang.String”);
4.通过类的加载器(类加载器是用来把类(class)装载进内存的)(了解)
ClassLoader cl = this.getClass().getClassLoader();
Class clazz4 = cl.loadClass(“类的全类名”);

public void test4() throws ClassNotFoundException{
//调用运行时类本身的.class属性
Class cla1=Person.class;
System.out.println(cla1.getName());//返回com.atguigu.java.Person
Class cla2=String.class;
System.out.println(cla2.getName());//返回java.lang.String

//通过运行时类的对象获取
Person p=new Person();
Class cla3=p.getClass();
System.out.println(cla3.getName());//返回com.atguigu.java.Person

//通过运行时类的静态方法forName获取
Class cla4=Class.forName("com.atguigu.java.Person");
System.out.println(cla4.getName());//返回com.atguigu.java.Person
}


创建类对象并获取类的完整结构:
创建类的对象:调用Class对象的newInstance()方法
要求:1)类必须有一个无参数的构造器。
2)类的构造器的访问权限需要足够。

//1.根据全类名获取对应的Class对象
String name = “atguigu.java.Person";
Class clazz = Class.forName(name);
//2.调用指定参数结构的构造器,生成Constructor的实例
Constructor con = clazz.getConstructor(String.class,Integer.class);
//3.通过Constructor的实例创建对应类的对象,并初始化类属性
Person p2 = (Person) con.newInstance("Peter",20);
System.out.println(p2);

通过反射调用类中的指定方法、指定属性:
1.调用指定属性
先获取属性
public Field getField(String name) 返回此Class对象表示的类或接口的指定的public的Field。
public Field getDeclaredField(String name)返回此Class对象表示的类或接口的指定的Field。
在Field中:
public Object get(Object obj) 取得指定对象obj上此Field的属性内容
public void set(Object obj,Object value) 设置指定对象obj上此Field的属性内容
注:在类中属性都设置为private的前提下,在使用set()和get()方法时,首先要使用Field类中的setAccessible(true)方法将需要操作的属性设置为可以被外部访问。
public void setAccessible(true)访问私有属性时,让这个属性可见。
2.调用指定方法

通过反射,调用类中的方法,通过Method类完成。步骤:
1).通过Class类的getMethod(String name,Class…parameterTypes)方法取得一个Method对象,并设置此方法操作时所需要的参数类型。
2).之后使用Object invoke(Object obj, Object[] args)进行调用,并向方法中传递要设置的obj对象的参数信息。

//调用运行时类中指定的属性
public void test5() throws Exception{
Class cla=Person.class;
//1.获取指定的属性
Field name=cla.getField("name");
//2.创建运行时类的对象
Person p=(Person)cla.newInstance();
//3.将运行时类的指定的属性赋值
name.set(p, "LiMing");
System.out.println(p);

Field age=cla.getDeclaredField("age");
age.setAccessible(true);
age.set(p, 20);
System.out.println(p);
}
//调用运行时类中指定的方法
public void test6() throws Exception{
Class cla=Person.class;
//获取运行时类中声明为public的指定的方法
Method m1=cla.getMethod("show");
Person p=(Person)cla.newInstance();
//调用指定的方法
Object returnVal=m1.invoke(p);

//对于运行时类中静态方法的调用,无需创建运行时类的对象,直接使用类调用对象
Method m2=cla.getMethod("info");
m2.invoke(Person.class);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: