Java 反射
反射:在运行状态中,对于任意一个类,能够知道这个类的所有属性和方法;对于任意一个对象,能够调用它的任意方法和属性;并且能够改变它的属性。
反射机制允许程序在运行时取得一个已知名称的class的内部信息,即修饰符、属性、方法,并且可在运行时改变属性或者调用方法。
**缺点:**反射使用不当会造成很高的资源浪费。使用反射会打破封装性,导致对象的属性不安全。
一个JVM中只有一个Class实例。
1、得到Class的三种方式:
package binaryheap.test;
//定义一个Person类
class Person{
private String name = "TxL";
public int age = 14;
public Person() {
}
private void say() {
System.out.println("private method");
}
public void sing() {
System.out.println("public method");
}
}
//测试
public class BH {
public static void main(String[] args) throws ClassNotFoundException {
//1通过对象
Person p1 = new Person();
Class c1 = p1.getClass();
//2通过类
Class c2 = Person.class;
//3通过Class类
Class c3 = Class.forName("binaryheap.test.Person");
System.out.println("c1==c2? " + (c1 == c2) );
System.out.println("c1==c3? " + (c1 == c3));
}
}
结果
c1==c2? true
c1==c3? true
2、通过Class类获取成员变量、成员方法、接口、超类、构造方法等
方法 | 描述 |
---|---|
getName() | 获取本类的完整名字 |
getField() | 获取类public类型的属性(包括从父类继承来的) |
getDeclaredFields() | 获取本类的所有属性(不包括继承来的) |
getMethod(String name,Class[] parameterTypes) | 根据方法名和形参类型获取方法 |
getMethods() | 获取本类的public类型的方法(包括父类中的public修饰的方法) |
getDeclaredMethod() | 获取本类中所有的方法(不包括从父类继承的) |
getConstructor(Class[] parameterTypes) | 根据参数获取构造方法 |
getConstructors() | 获取类的public类型的构造方法 |
newInstance() | 通过类的不带参数的构造器创建一个对象 |
例:
package binaryheap.test;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
//定义一个Person类
class Person{
private String name = "TxL";
public int age = 14;
public Person() {
}
private void say() {
System.out.println("private method");
}
public void sing() {
System.out.println("public method");
}
}
//测试
public class BH {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException {
//1通过对象
Person p1 = new Person();
Class c1 = p1.getClass();
//2通过类
Class c2 = Person.class;
//3通过Class类
Class c3 = Class.forName("binaryheap.test.Person");
System.out.println("c1==c2? " + (c1 == c2) );
System.out.println("c1==c3? " + (c1 == c3));
System.out.println("-----------------------------------------");
System.out.println("-------------------得到Class之后----------------------");
//1、类的完整名字
String className = c1.getName();
System.out.println("Person类的完整名字: " + className );
System.out.println("---------------------------------------------------");
//2、获取public属性
Field[] fields = c1.getFields();
for(Field field : fields) {
System.out.println("输出field.getName " + field.getName());
}
System.out.println("---------------------------------------------------");
//3、获取所有的属性
Field[] fields2 = c1.getDeclaredFields();
for(Field field : fields2) {
System.out.println("输出field.getName " + field.getName());
}
System.out.println("---------------------------------------------------");
//4、获取类的public方法
Method[] methods = c1.getMethods();
for (Method method : methods) {
System.out.println("method.getName: " + method.getName());
}
System.out.println("---------------------------------------------------");
//5、获取类的所有方法
Method[] methods2 = c1.getDeclaredMethods();
for (Method method : methods2) {
System.out.println("method.getName: " + method.getName());
}
System.out.println("---------------------------------------------------");
//6、获取指定的属性
Field field = c1.getDeclaredField("name");
field.setAccessible(true);
System.out.println("field: " + field);
System.out.println("---------------------------------------------------");
//7、创建一个此类的对象
Object p2 = c1.newInstance();
field.set(p2, "zzy");
System.out.println(field.get(p2));
}
}
输出
c1==c2? true
c1==c3? true
-----------------------------------------
-------------------得到Class之后----------------------
Person类的完整名字: binaryheap.test.Person
---------------------------------------------------
输出field.getName age
---------------------------------------------------
输出field.getName name
输出field.getName age
---------------------------------------------------
method.getName: sing
method.getName: wait
method.getName: wait
method.getName: wait
method.getName: equals
method.getName: toString
method.getName: hashCode
method.getName: getClass
method.getName: notify
method.getName: notifyAll
---------------------------------------------------
method.getName: say
method.getName: sing
---------------------------------------------------
field: private java.lang.String binaryheap.test.Person.name
---------------------------------------------------
zzy