Java反射机制
Posted qust-lgh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java反射机制相关的知识,希望对你有一定的参考价值。
Java让我们在识别对象和类的信息,主要有两种方式:一种是传统的RTTI,它假定我们在编译时已经知道了所有的类型信息;另一种是反射机制,它允许我们在运行时发现和使用类的信息。
使用反射赋予了Java动态编译的能力,否则类的元数据信息只能通过静态编译的方式实现。
Java中编译类型有两种:
静态编译:在编译时确定类型,绑定对象即通过
动态编译:运行时确定类型,绑定对象。动态编译最大限度地发挥了Java的灵活性,体现了多态的应用,可以降低类之间的耦合性。
什么是反射?
反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。
Java Reflection
反射是被视为动态语言的关键,反射机制允许程序在执行期间借助Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性和方法。
Java反射机制提供的功能
在运行时判断任意一个对象所属的类
在运行的时候构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时调用任意一个对象的成员变量和方法
public class Person {
public String name;
private int age;
public int id;
public Person() {
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = 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);
}
public static void info(){
System.out.println("元宵节快乐!");
}
}
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import org.junit.Test;
public class TestField {
// 获取对应运行时类的属性
@Test
public void test1(){
Class clazz = Person.class;
// 1.getFields():只能获取运行时类中及其父类声明为public的属性
Field[] fields = clazz.getFields();
for (int i = 0; i < fields.length; i++) {
System.out.println(fields[i].getName());
}
//2.getDeclaredFields():获取运行时类本身声明的所有属性
Field[] fields2 = clazz.getDeclaredFields();
for (Field f : fields2) {
System.out.println(f.getName());
}
}
// 获取权限修饰符 变量类型 属性名
@Test
public void test2(){
Class clazz = Person.class;
Field[] fields = clazz.getDeclaredFields();
for (Field f : fields) {
// 1.获取每个属性的访问修饰符
int i = f.getModifiers();
System.out.println(Modifier.toString(i)+" ");
// 2.获取属性的类型
Class type = f.getType();
System.out.println(type.getName()+" ");
// 3.获取属性名
System.out.println(f.getName()+" ");
System.out.println();
}
}
// 调用运行时类中指定的属性
@Test
public void test3() throws Exception{
Class clazz = Person.class;
// 1.获取指定的属性
// getField(String fieldName):获取运行时类中声明为public的属性名
Field name = clazz.getField("name");
// 2.创建运行时类的对象
Person p = (Person) clazz.newInstance();
System.out.println(p);
// 3.将运行时类的属性赋值
name.set(p, "jack");
System.out.println(p);
// 4.getDeclaredField(String fieldName):获取运行时类中指定的名为fieldName的属性
Field age = clazz.getDeclaredField("age");
// 由于属性权限修饰符的限制,为了保证可以为属性赋值,需要在操作前使得此属性可以被操作。
age.setAccessible(true);
age.set(p, 20);
System.out.println(p);
}
}
import java.lang.reflect.Constructor;
import org.junit.Test;
public class TestConstructor {
@Test
public void test1() throws Exception{
// 创建对应运行时类的对象使用newInstance()实际上是调用了运行时类的空参构造器
// 要求:1.对应的运行时类要有空参的构造器 2.构造器的权限修饰符权限要足够
String className = "com.hpe.reflect.Person";
Class clazz = Class.forName(className);
Person p = (Person) clazz.newInstance();
System.out.println(p);
}
// 获取Person类中所有的构造器
@Test
public void test2() throws Exception{
Class clazz = Class.forName("com.hpe.reflect.Person");
Constructor[] cons = clazz.getDeclaredConstructors();
for (Constructor c : cons) {
System.out.println(c);
}
}
// 调用指定的构造器
@Test
public void test3() throws Exception{
Class clazz = Class.forName("com.hpe.reflect.Person");
Constructor cons = clazz.getDeclaredConstructor(String.class,int.class);
cons.setAccessible(true);
Person p = (Person) cons.newInstance("张三",20);
System.out.println(p);
}
}
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.junit.Test;
public class TestMethod {
// 调用运行时类中指定的方法
@Test
public void test1() throws Exception{
Class clazz = Person.class;
// getMethod(String methodName,class... params):获取运行时类中声明为public的方法
Method m1 = clazz.getMethod("show");
Person p = (Person) clazz.newInstance();
// 调用指定的方法Object invoke(Object obj,Object... obj)
Object returnVal = m1.invoke(p);
System.out.println(returnVal);
// 带有返回值类型的方法
Method m2 = clazz.getMethod("toString");
// 设置属性值
Field name = clazz.getField("name");
name.set(p, "lim");
Object returnVal2 = m2.invoke(p);
System.out.println(returnVal2);
// 调用静态方法
Method m3 = clazz.getMethod("info");
m3.invoke(Person.class);
// getDeclaredMethod(String methodName,class...param):获取运行时类声明的指定方法
Method m4 = clazz.getDeclaredMethod("display", String.class);
m4.setAccessible(true);
m4.invoke(p, "CHN");
}
}
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.junit.Test;
public class TestReflection {
// 通过传统方式调用对象 调用其方法
@Test
public void test1(){
Person p = new Person();
p.setAge(15);
p.setName("jack");
System.out.println(p);
p.show();
p.display("山东");
}
// 有了反射,可以通过反射创建一个类的对象,并调用其中的结构
@Test
public void test2() throws Exception{
Class clazz = Person.class;
// 1.创建clazz对应运行时类Person类的对象
Person p = (Person)clazz.newInstance();
System.out.println(p);
// 2、通过反射调用运行时类指定的属性
Field f1 = clazz.getField("name");
// 设置某个对象的属性值
f1.set(p, "jack");
System.out.println(p);
Field f2 = clazz.getDeclaredField("age");
// 设置允许访问
f2.setAccessible(true);
f2.set(p, 20);
System.out.println(p);
// 3.通过反射调用运行时类指定的方法
Method m1 = clazz.getMethod("show");
// 调用方法
m1.invoke(p);
Method m2 = clazz.getMethod("display", String.class);
m2.invoke(p, "China");
}
/*
* java.lang.Class:反射的源
* 创建一个类,通过编译(javac.exe)生成对应的class文件,之后我们通过java.exe(JVM类加载器)加载此class文件
* 到内存,就是一个运行时类,存放在缓存区。Class clazz = Person.class
* 1.每个运行时类只加载一次
* 2.有了Class实例后,可以执行:
* ①.创建对应运行时类的对象(重点)
* ②.获取对应运行时类的完整结构(属性、方法、构造器、内部类、父类、包、异常、注解)
* ③.调用对应的运行时类的指定结构(属性、方法、构造器)(重点)
*/
@Test
public void test3(){
Person p = new Person();
// 调用其getClass()方法返回运行时类
Class clazz = p.getClass();// Person.class
System.out.println(clazz);
}
@Test
public void test4() throws ClassNotFoundException{
// 1.调用类本身的.class属性
Class clazz1 = Person.class;
System.out.println(clazz1.getName());
Class clazz2 = String.class;
System.out.println(clazz2.getName());
// 2.通过类的对象获取
Person p = new Person();
Class clazz3 = p.getClass();
System.out.println(clazz3.getName());
// 3.通过Class类的静态方法获取
String className = "com.hpe.reflect.Person";
Class clazz4 = Class.forName(className);
System.out.println(clazz4.getName());
// 4.通过类的加载器(了解)
ClassLoader classLoader = this.getClass().getClassLoader();
Class clazz5 = classLoader.loadClass(className);
System.out.println(clazz5.getName());
}
}
以上是关于Java反射机制的主要内容,如果未能解决你的问题,请参考以下文章