@[TOC]希望本文能帮助你增加对反射的理解
反射的简单叙述及相关性质
反射的源头 —— Class类
反射的主要应用
反射的简单叙述及相关性质
- 能够分析类能力的程序为反射,反射机制的功能极其强大,下面我们就来简单举个例子
public class Student {
private String name;
private int age;
private int id;
private Student(){
name = "";
age = 0;
id = 0;
}
private void showInfo(){
System.in.println("Hello world");
}
}
出了Student类,由于封装性的缘故,我们就不能直接调用那些私有的结构(属性、方法、构造器),但使用了反射,我们就可以调用运行时类的任意结构。*可能有的人会认为反射与封装性相矛盾,但实际上并不这样,封装性中private表示的是并不建议你调用该属性,但反射主要是表现能不能调用,所以二者并不矛盾。*其次,反射主要是开发工具的程序员对他感兴趣(比如框架的底层实现机制就有反射,学习反射有助于你对框架底层原码的理解),一般的程序员不怎么会用到反射。
反射的源头 – Class类
1.Class类的理解
当我们对java文件进行编译时,会生成一个或多个.class字节码文件,接着我们试着去运行java程序,会将.class文件加载到内存中,每个.class的结构就对应着一个Class类的实例
那么,Clas类又可以指向哪些java文件呢?
(1)primitive type:基本数据类型
(2)interface:接口
(3)[]:数组
(4)enum:枚举
(5)annotation:注解
(6)class:外部类、内部类
(7)void
也就是说,java中的所有类型!
2.获取Class类的实例的主要的几种方式
① 类名.class
Class aClass = Student.class;
② 运行时类对象的getClass()方法
Student std = new Student();
Class aClass = std.getClass();
③ Class类的静态方法forName(“className”)
String className = "java.util.Random";//此处传入的参数是类的全类名,这样才能具体的知道你需要的是哪个类
Class aClass = Class.forName(className);
尽管看上去第一种方式是最方便、最快捷的,但是方法三是不是更能体现反射的动态性呢?通过传入不同的全类名来获取Class类的实例,然后再进行后续操作。
- 注意 :Class类的getName()方法应用在数组类型会返回一些奇怪的东西
- 如
Class aClass = int[].class;
System.out.println(aClass.getName());
会显示"[I;"
*
反射的主要应用
在介绍反射的主要应用前,我先给大家看看我用反射所调用的Student类的结构,且为了代码等简单一些,我在其中遇到的异常都先用throws抛出异常
public class Student {
private int age;
private String name;
public Student() {
}
public Student(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
private String showInfo(){
return "name = " + name + ",age = " + age;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
① 调用指定的构造器
@Test
public void test() throws Exception {
Class aClass = Student.class;//获取类的实例
//下面这步适用于获取类的指定构造器,像我这种传入的是String.class和int.class就对应着指定构造器的形参列表的参数类型
Constructor declaredConstructor = aClass.getDeclaredConstructor(String.class, int.class);
//这步主要是为了设置构造器的权限,防止我们没有足够的权限调用构造器,有了这步,可以看到即使是private修饰的构造器我们也 可以调用,属性和方法也是如此,就不再过多赘述了
declaredConstructor.setAccessible(true);
//这步就是创建类对应的实例
Student std = (Student) declaredConstructor.newInstance("Tony", 18);
System.out.println(std);
}
在讲述接下来的有关于反射的运用时,先来介绍一下在jdk9.0中被弃用的Class的newInstance()方法
Class aClass = Student.class;
Student std = (Student) aClass.newInstance();
使用上述的代码同样也可以创建Student类的一个实例,但是对Student类有一定的要求,必须有一个空参的构造器,且该构造器的访问权限还需要达到一定的条件,为了方便,我接下来都用此方法创建类的实例
② 调用指定的属性
@Test
public void test() throws Exception {
Class aClass = Student.class;
Student std = (Student) aClass.newInstance();
//这步主要时找到Student类的名为name的属性
Field nameField = aClass.getDeclaredField("name");
nameField.setAccessible(true);
//设置指定对象的name属性的值
nameField.set(std,"jerry");
//获取指定对象的name属性的值,返回值类型为Object
System.out.println(nameField.get(std));
}
③ 调用指定的方法
@Test
public void test7() throws Exception {
Class aClass = Student.class;
Student std = (Student) aClass.newInstance();
//调用Student类中名为showInfo的方法,形参为String类
Method showInfo = aClass.getDeclaredMethod("showInfo", String.class);
showInfo.setAccessible(true);
//invoke即为方法的调用,传入参数为所对应的对象和实参,返回值即为对应方法的返回值,如果返回值为void的话,则返回null
String returnValue = (String) showInfo.invoke(std, "CHINA");
System.out.println(returnValue);
}
}
好了,以上就是关于反射的一些比较基础但比较主要的知识点,希望能对于你对反射的学习有所帮助
标签:反射,java,入门,aClass,Class,Student,class,name From: https://blog.csdn.net/2301_80113755/article/details/142469577