JAVA中的反射机制
文章目录
反射机制-获取类对象
什么是类对象?
- 所有的类,都有一个类对象,这个类对象用于提供类本身的信息。比如有多少构造方法,有多少属性,有哪些普通方法。
如何获取类对象
-
获取类对象有3种方式
Class.forName
类名.class
new 类名.getClass()
-
在JVM中,一种类只会有一个类对象存在,所以以上三种方式所获取的类对象,都是一样的。
-
准确的来讲,是一个
ClassLoader
下,一种类只有一个类对象存在 -
代码实现:
package reflection;
/**
* @author xsl20
*/
public class GetInstanceForClass {
public static void main(String[] args){
String className = "reflection.Hero";
try{
Class pClass1 = Class.forName(className);
Class pClass2 = Hero.class;
Class pClass3 = new Hero("garren",12,1010).getClass();
}catch(ClassNotFoundException e){
e.printStackTrace();
}
}
}
- 当以上三种方法获取类对象时,都会导致静态属性被初始化,而其他属性不会,而且这种初始化只会执行一次。
public class Hero{
static String copyright;
static {
System.out.println("copyright被初始化!");
}
}
- 在Hero类添加了上面的静态属性之后,再次执行上面的获取类对象的代码,将会发现,
Hero
类的静态属性copyright
执行了仅一次。
反射机制-创建对象
- 反射机制创建对象和正常的使用
new
来创建对象不同,反射机制会先拿到类对象,然后通过类对象获取构造器对象,再通过构造器对象来创建一个对象。
创建一个对象
- 通过java的反射机制来创建一个对象
- 代码实现:
package reflection;
import java.lang.reflect.Constructor;
import charactor.Hero;
public class TestReflection {
public static void main(String[] args) {
//传统的使用new的方式创建对象
Hero h1 =new Hero();
h1.name = "teemo";
System.out.println(h1);
try {
//使用反射的方式创建对象
String className = "charactor.Hero";
//类对象
Class pClass=Class.forName(className);
//构造器
Constructor c= pClass.getConstructor();
//通过构造器实例化
Hero h2= (Hero) c.newInstance();
h2.name="gareen";
System.out.println(h2);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
通过配置文件创建获取文件
- 从配置文件
hero.config
中获取其中的保存的类的全名称,可以是character.APHero
或者character.ADHero
,根据类名来实现对象的实例化。 - 代码实现:
package reflection;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Constructor;
public class CodeGetHero {
public static void main(String[] args){
getHero();
}
public static Hero getHero(){
File file = new File("D:/javaWorkspace/Hero.config");
String className = "";
try(FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader)){
className = bufferedReader.readLine();
}catch (IOException e){
e.printStackTrace();
}
System.out.println(className);
Hero hero = null;
try {
Class pClass = Class.forName(className);
Constructor constructor = pClass.getConstructor();
hero = (Hero)constructor.newInstance();
hero.name = "garen";
}catch(Exception e){
e.printStackTrace();
}
System.out.println(hero);
return hero;
}
}
反射机制- 访问属性
通过反射机制来访问和修改对象的属性
- 为了访问属性,需要将
Hero
类的属性name
设置为public
,这样才能顺利的完成访问。 - 如果需要访问
private
的属性,必须使用setAccessible(true)
才能进行访问和修改。 - 代码实现:
public class TestReflection{
public static void main(String[] args){
//新建一个对象
Hero hero = new Hero();
//设置对象的字段
hero.name = "tse";
try{
//获取对象的字段
Field field = hero.getClass().getDeclaredField("name");
//设置对象的字段
field.set(hero,"newTse");
System.out.println(hero);
}catch(NoSuchFieldException e){
e.printStackTrace();
}catch(IllegalAccessException e1){
e1.printStackTrace();
}
}
}
-
通过类对象来获取对象的字段可以使用
getField(fieldName)
或者使用getDeclaredField(FieldName)
来实现,这两个方法有一些不同之处:getField()
方法只能获取public
的字段,包括从父类继承来的字段。getDeclaredField()
方法能够该对象的所有字段,但是不包含继承来的。能够获取private
的字段,但是并不能访问该值,除非使用setAccessible(true)
-
代码实现:
Field field = hero.getClass().getDeclaredField("num");
field.setAccessible(true);
field.set(hero,111111);
反射机制- 调用方法
- 通过java的反射特性,调用一个方法。
调用方法
- 通过反射来调用Hero类的
getName
和setName
方法。 - 代码实现:
public static void useGetAndSet(String name){
Hero hero = new Hero();
hero.name = "garen";
hero.num = 110;
try{
//利用反射机制获取hero的方法getNum
Method method = hero.getClass().getDeclaredMethod("getNum");
//调用getNum方法得到Num
int num = (int)method.invoke(hero,null);
//打印结果为110
System.out.println(num);
}
}
反射机制- 有什么用处
- java的反射特性非常强大,但是在基础阶段并不知道反射有什么用处
- 简单来讲,当有两个业务类需要进行方法测试时,如果不使用反射,就只能通过修改代码来实现两个不同类的测试工作,但是如果使用反射,只需要从
config
文件中加载类和方法名来测试就可以。当需要更换测试类的时候,就只需要修改config
文件而不需要更改代码。
来源:CSDN
作者:江湖大梦1874
链接:https://blog.csdn.net/qq_42033377/article/details/104512248