Java反射详解——一篇文章读懂java反射机制

本文详细介绍了Java的反射机制,包括如何访问和调用非静态成员和方法,涉及构造方法、成员变量、接口方法的访问,以及静态成员、静态方法的使用。通过实例演示了Method类的方法如invoke的运用,同时也讲解了如何访问静态内部类、非静态内部类和匿名类。此外,还探讨了如何利用反射获取和操作注解。
摘要由CSDN通过智能技术生成

1. 前言

JAVA反射机制能够在运行状态中,对于任意一个类,都能够访问这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态访问成员以及动态调用对象方法的功能称为java语言的反射机制。

2. 非静态成员和非静态方法的访问和调用

首先先举一个类作为例子,后续操作都是对这个类进行反射的测试:

package advance.reflect;

public class NoStaticTest {
   
    private int id;
    public String name;
    public float score;

    public NoStaticTest() {
   
    }

    private NoStaticTest(int id, String name, float score) {
   
        this.id = id;
        this.name = name;
        this.score = score;
    }

    public void public_fun() {
   
        System.out.println(toString() + "   called public function");
    }

    private void private_fun() {
   
        System.out.println(toString() + "   called private function");
    }

    public int public_fun_namelen(String name) {
   
        System.out.println(toString() + "   called public (int)function(String)");
        return name.length();
    }

    private int private_fun_namelen(String name) {
   
        System.out.println(toString() + "   called private (int)function(String)");
        return name.length();
    }

    @Override
    public String toString() {
   
        return "NoStaticTest{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", score=" + score +
                '}';
    }
}

这个类包含的非静态成员和方法的所有情况,包括private、public(protect的在访问许可范围内参照public,访问许可范围外参照private),数据类型包括普通类型(int和float)、引用类型(String),方法包括有参数、无参数、有返回值、无返回值的所有情况,构造方法也分有参和无参。可以说总结很全面了。
接下来就是使用的例子:

1. 关于构造方法

public static void test1() {
   
	try {
   
		Class cls = Class.forName("advance.reflect.NoStaticTest");
		NoStaticTest noStaticTest1 = (NoStaticTest) cls.newInstance();
		System.out.println("cls.newInstance() : " + noStaticTest1);

		Constructor[] constructors = cls.getConstructors();
		System.out.println("public构造方法:");
		for (Constructor constructor : constructors) {
   
			System.out.println(constructor);
		}
		System.out.println("所有构造方法:");
		constructors = cls.getDeclaredConstructors();
		for (Constructor constructor : constructors) {
   
			System.out.println(constructor);
		}

		NoStaticTest noStaticTest2 = (NoStaticTest) cls.getConstructor().newInstance();
		System.out.println("constructor.newInstance() : " + noStaticTest2);

		Constructor private_construct = cls.getDeclaredConstructor(int.class, String.class, float.class);
		private_construct.setAccessible(true);
		NoStaticTest noStaticTest3 = (NoStaticTest) private_construct.newInstance(1, "ABC", 99.99f);
		System.out.println("constructor.newInstance() : " + noStaticTest3);

	} catch (Exception e) {
   
		e.printStackTrace();
	}
}

运行结果:
cls.newInstance() : NoStaticTest{id=0, name=‘null’, score=0.0}
public构造函数:
public advance.reflect.NoStaticTest()
所有构造函数:
public advance.reflect.NoStaticTest()
private advance.reflect.NoStaticTest(int,java.lang.String,float)
constructor.newInstance() : NoStaticTest{id=0, name=‘null’, score=0.0}
constructor.newInstance() : NoStaticTest{id=1, name=‘ABC’, score=99.99}

Class类中的方法名 作用描述
getConstructors 返回值是Constructor[]类型,可以获取类中所有公共构造方法,不需要参数
getDeclaredConstructors 返回值是Constructor[]类型,可以获取类中所有构造方法(包括私有的),不需要参数
getConstructor 返回值是Constructor类型,可以获取类中所有公共构造方法,可以需要参数,有参数时会按照参数指定的构造方法参数表进行查找
getDeclaredConstructor 返回值是Constructor类型,可以获取类中所有构造方法(包括私有的),可以需要参数,有参数时会按照参数指定的构造方法参数表进行查找
补充 1:当无法访问时可以通过设置setAccessible(true)的方式修改权限
补充 2:可以需要参数的意思是可以要也可以不要,原因是(拿getConstructor举个例子)getConstructor的参数列表用的是不定长参数

public Constructor getConstructor(Class<?>… parameterTypes)

2. 关于成员变量

public static void test2() {
   
	try {
   
		Class cls = Class.forName("advance.reflect.NoStaticTest");
		NoStaticTest noStaticTest = (NoStaticTest) cls.getDeclaredConstructor().newInstance();

		Field[] fields = cls.getFields();
		System.out.println("public成员:");
		for (Field field : fields) {
   
			System.out.println(field.getName() + ":" + field.getType());
		}
		System.out.println("所有成员:");
		fields = cls.getDeclaredFields();
		for (Field field : fields) {
   
			System.out.println(field.getName() + " : " + field.getType() + "  :  " + field.canAccess(noStaticTest));
		}
		System.out.println("尝试访问所有成员:");
		for (Field field : fields) {
   
			if (!field.canAccess(noStaticTest)) {
   
				field.setAccessible(true);
				System.out.println(field.getName() + " is private, I will get access...");
			}
			if (field.getType().equals(int.class)) {
   
				field.setInt(noStaticTest, 1);
			} else if (field.getType().equals(String.class)) {
   
				field.set(noStaticTest, "ABC");
			} else {
   
				field.setFloat(noStaticTest, 99.99f);
			}
		}
		System.out.println(noStaticTest);
	} catch (Exception e) {
   
		e.printStackTrace();
	}
}

运行结果:
public成员:
name:class java.lang.String
score:float
所有成员:
id : int : false
name : class java.lang.String : true
score : float : true
尝试访问所有成员:
id is private, I will get access…
NoStaticTest{id=1, name=‘ABC’, score=99.99}

Class类中的方法名 作用描述
getFields 返回值是Field[]类型,可以获取类中所有公共成员(包括继承的
getDeclaredFields 返回值是Field[]类型,可以获取类中所有在这个类中声明或者覆盖的成员包括私有的
补充 1:当无法访问时可以通过设置setAccessible(true)的方式修改权限
补充 2:可以发现两个方法都不能访问到父类的私有成员,那么父类的私有成员能不能访问呢?答案肯定是:能。
关于父类的私有成员和私有方法

这个地方把父类的私有方法也一起说了,因为方法非常类似。
使用getSuperclass这个方法可以获得父类的Class对象,由于Java是单继承,所以不存在多个父类的情况。

补充 3:那么该怎么访问实现接口的方法呢?

关于实现接口的方法

getInterfaces方法可以获取所有的实现接口的Class对象并以数组返回,然后后续操作就不用细说了。

关于访问非静态成员

细心的人会发现,当我使用getType方法的时候

3. 关于方法调用

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值