其他
原创 | 一篇了解Java反射
点击蓝字
关注我们
反射
反射实例理解
package Sentiment.refelction;
public class A {
private String name="refelction";
public int age=10;
public void a(){
System.out.println("this is =>A");
}
public void b(){
System.out.println("this is =>B");
}
}
path=Sentiment.refelction.A
method=a
传统方式
A cat = new A();
cat.a();
I/O流根据配置文件读取
Properties properties = new Properties();
properties.load(new FileInputStream("re.properties"));
String path = properties.get("path").toString(); //Sentiment.refelction.A
String method = properties.get("method").toString(); // a
new path().a(); //报错
反射,这时就可以通过反射将String类型的path,转为Class类型的对象进行调用
//(1) 获取Class类型的对象c1
Class c1 = Class.forName(path);
//System.out.println(c1);
//(2) 通过c1 得到加载的类 Sentiment.refelction.A的对象实例
Object o = c1.newInstance();
System.out.println("o的运行类型是:"+o.getClass());
//(3)通过c1 得到加载的类Sentiment.refelction.A 的method的方法对象"a"
Method method1 =c1.getMethod(method);
//(4)通过method1 调用方法对象来实现调用方法
method1.invoke(o);//传统方法 对象.方法() ,反射 方法.invoke(对象)
A cat = new A();
cat.b();
path=Sentiment.refelction.A
method=a
反射优缺点
优点
缺点
Class类
介绍
public class Class01 {
public static void main(String[] args) throws ClassNotFoundException {
//每个类的Class类对象,在内存中只有一份,因为类只加载一次
Class c1 = Class.forName("Sentiment.refelction.A");
Class c2 = Class.forName("Sentiment.refelction.A");
System.out.println(c1.hashCode());
System.out.println(c2.hashCode());
}
}
Class类常用方法
package Sentiment.refelction;
public class Car {
public String brand="宝马";
public int price = 5000000;
public String color = "白色";
@Override
public String toString() {
return "Car{" +
"brand='" + brand + '\'' +
", price=" + price +
", color='" + color + '\'' +
'}';
}
}
package Sentiment.refelction;
import java.lang.reflect.Field;
public class Class02 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
String path="Sentiment.refelction.Car";
//1. 获取Car类对应的Class对象
Class c1 = Class.forName(path);
//2. 输出c1
System.out.println(c1); //显示c1对象是哪个类的Class对象 Sentiment.refelction.Car
System.out.println(c1.getClass());//输出c1运行类型 java.lang.Class
//3.获取包名
System.out.println(c1.getPackage().getName());
//4.得到类的全路径
System.out.println(c1.getName());
//5. 通过c1创建对象实例
Car car = (Car)c1.newInstance();
System.out.println(car); //输出car时自动调用toString()方法
//6. 通过反射获取属性
Field brand = c1.getField("brand");
System.out.println(brand.get(car));
//7.通过反射给属性赋值
brand.set(car,"奔驰");
System.out.println(brand.get(car));
//8.获取所有属性及属性值
Field[] fields = c1.getFields();
for(Field f : fields){
System.out.print(f.getName()+":"); //属性名
System.out.print(f.get(car)+" "); //属性值
}
}
}
获取Class类对象
Class c1=Class.forName("Sentiment.refelction.Car")
Class c2=Car.class
Car car = new Car();
Class c3 = car.getClass();
//(1)先得到加载器
ClassLoader classLoader = car.getClass().getClassLoader();
//(2)通过类加载器得到Class对象
Class c4 =classLoader.loadClass(path);
5.基本数据
(int, char, boolean,float,double,byte,
long,short)按如下方式得到Class类对象
Class c5 = 基本数据类型.class
Class c6 = 包装类.type
package Sentiment.refelction;
public class GetClass {
public static void main(String[] args) throws ClassNotFoundException {
//1.Class.forName)
String path="Sentiment.refelction.Car"; //通过读取配置文件获取
Class c1 = Class.forName(path);
System.out.println(c1);
//2.类名.class,用于参数传递
Class c2 = Car.class;
System.out.println(c2);
//3.对象.getClass(),用于有对象实例
Car car = new Car();
Class c3 = car.getClass();
System.out.println(c3);
//4.通过类加载器来获取Class类对象
//(1)先得到加载器car
ClassLoader classLoader = car.getClass().getClassLoader();
//(2)通过类加载器得到Class对象
Class c4 =classLoader.loadClass(path);
System.out.println(c4);
//5.基本数据(int, char, boolean,float,double,byte,long,short)按如下方式得到Class类对象
Class c5 = int.class;
Class<Character> characterClass = char.class;
//6.基本数据类型对应的包装类,可以通过type得到Class类对象
Class<Integer> type = Integer.TYPE;
Class<Character> type1 = Character.TYPE;
System.out.println(type);
}
类加载分类
package Sentiment.refelction;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Scanner;
public class ClassLoad {
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
String key = scanner.next();
switch (key){
case "1":
Dog dog = new Dog();
dog.cry();
break;
case "2":
System.out.println("ok");
break;
default:
System.out.println("Do nothing!");
}}
}
new Dog()就会报错找不到该类
而当使用动态加载,也就是反射机制时
package Sentiment.refelction;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Scanner;
public class ClassLoad {
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
String key = scanner.next();
switch (key){
//静态加载
case "1":
//Dog dog = new Dog();
//dog.cry();
//break;
//反射动态加载
case "2":
Class c1 = Class.forName("Person");
Object o = c1.newInstance();
Method method = c1.getMethod("hi");
method.invoke(o);
System.out.println("ok");
break;
default:
System.out.println("Do nothing!");
}}
}
类加载时机
当创建对象时(new) //静态加载 当子类被加载时,父类也加载 //静态加载 调用子类中的静态成员时 //静态加载 通过反射 //动态加载
通过反射获取类的结构信息
java.lang.Class类API
getName:获取全类名 getSimpleName:获取简单类名 getFields:获取所有pubulic修饰的属性,包括本类以及父类的 getDeclaredFields:获取本类中所有属性 getMethods:获取所有public修饰的方法,包含本类以及父类的(父类包括Object类) getDeclaredMethods:获取本类中的所有方法 getConstrctors:获取所有本类的public修饰的构造器 getDeclaredConstructors:获取本类中的所有构造器 getPackage:以Package形式返回包信息 getSuperClass:以Class形式返回父类信息 getInterfaces:以Class[]形式返回接口信息 getAnnotations:以Annotation[] 形式返回注解信息
package Sentiment.refelction;
import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectionUtils {
public static void main(String[] args) throws ClassNotFoundException {
new ReflectionUtils().api();
}
public void api() throws ClassNotFoundException {
Class c1 = Class.forName("Sentiment.refelction.Person");//获取Class对象
//getName:获取全类名
System.out.println(c1.getName());
//getSimpleName:获取简单类名
System.out.println(c1.getSimpleName());
//getFields:获取所有pubulic修饰的属性,包括本类以及父类的
Field[] fields = c1.getFields();
for (Field field : fields) {
System.out.println("本类以及父类的属性="+field.getName());
}
//getDeclaredFields:获取本类中所有属性
Field[] declaredFields = c1.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println("本类中所有属性="+declaredField.getName());
}
//getMethods:获取所有public修饰的方法,包含本类以及父类的(父类包括Object类)
Method[] methods = c1.getMethods();
for (Method method : methods) {
System.out.println("本类以及父类的public方法="+method.getName());
}
//getDeclaredMethods:获取本类中的所有方法
Method[] declaredMethods = c1.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println("本类中的所有方法="+declaredMethod);
}
//getConstrctors:获取所有本类的public修饰的构造器
Constructor[] constructors = c1.getConstructors();
for (Constructor constructor : constructors) {
System.out.println("本类的public构造器="+constructor);
}
//getDeclaredConstructors:获取本类中的所有构造器
Constructor[] declaredConstructors = c1.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println("本类中的所有构造器= "+declaredConstructor);
}
//getPackage:以Package形式返回包信息
System.out.println("包信息"+c1.getPackage());
//getSuperClass:以Class形式返回父类信息
System.out.println("父类的class对象= "+c1.getSuperclass());
//getInterfaces:以Class[]形式返回接口信息
Class[] interfaces = c1.getInterfaces();
for (Class anInterface : interfaces) {
System.out.println("接口信息= "+anInterface);
}
//getAnnotations:以Annotation[]形式返回注解信息
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println("注解信息= "+annotation);
}
}
}
interface IA{
}
interface IB{
}
class B{
public String hobby;
public void hi(){
}
public B() {
}
}
@Deprecated
class Person extends B implements IA,IB{
//属性
public String name;
protected int age;
String job;
private double sal;
//方法
public void m1(){
}
protected void m2(){
}
void m3(){
}
private void m4(){
}
//构造方法
public Person() {
}
public Person(String name) {
this.name = name;
}
}
Sentiment.refelction.Person
-----------------------------
Person
-----------------------------
本类以及父类的属性=name
本类以及父类的属性=hobby
-----------------------------
本类中所有属性=name
本类中所有属性=age
本类中所有属性=job
本类中所有属性=sal
-----------------------------
本类以及父类的public方法=m1
本类以及父类的public方法=hi
本类以及父类的public方法=wait
本类以及父类的public方法=wait
本类以及父类的public方法=wait
本类以及父类的public方法=equals
本类以及父类的public方法=toString
本类以及父类的public方法=hashCode
本类以及父类的public方法=getClass
本类以及父类的public方法=notify
本类以及父类的public方法=notifyAll
-----------------------------
本类中的所有方法=protected void Sentiment.refelction.Person.m2()
本类中的所有方法=void Sentiment.refelction.Person.m3()
本类中的所有方法=private void Sentiment.refelction.Person.m4()
本类中的所有方法=public void Sentiment.refelction.Person.m1()
-----------------------------
本类的public构造器=public Sentiment.refelction.Person()
本类的public构造器=public Sentiment.refelction.Person(java.lang.String)
-----------------------------
本类中的所有构造器= public Sentiment.refelction.Person()
本类中的所有构造器= public Sentiment.refelction.Person(java.lang.String)
-----------------------------
包信息package Sentiment.refelction
-----------------------------
父类的class对象= class Sentiment.refelction.B
-----------------------------
接口信息= interface Sentiment.refelction.IA
接口信息= interface Sentiment.refelction.IB
-----------------------------
注解信息= @java.lang.Deprecated()
-----------------------------
java.lang.feflect.Field类API
getModifiers:以int形式返回修饰符(默认修饰符—>0,public—>1,priva—>2,protected—>4,static—>8,final—>16。若为混合类型则相加计算 例:public+static = 1+8 = 9) getType:以Class形式返回类型 getName:返回属性名
java.lang.reflect.Method类API
getModifiers:以int形式返回修饰符 getReturnType:以Class形式获取返回类型 getName:返回方法名 getParameterTypes:以Class[]返回参数类型数组(即形参类型)
java.lang.reflect.Constructor类API
getModifiers:以int形式返回修饰符 getName:返回方法名 getParameterTypes:以Class[]返回参数类型数组
package Sentiment.refelction;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectionUtils02 {
public static void main(String[] args) throws ClassNotFoundException {
new ReflectionUtils02().api2();
}
public void api2() throws ClassNotFoundException {
Class c1 = Class.forName("Sentiment.refelction.Student");//获取Class对象
System.out.println("------------------------------");
System.out.println("java.lang.feflect.Field类API");
System.out.println("------------------------------");
//getDeclaredFields:获取本类中所有属性
Field[] declaredFields = c1.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println("本类中所有属性="+declaredField.getName()+" 该类的属性值="+declaredField.getModifiers()+" 类型是="+declaredField.getType());
}
System.out.println("------------------------------");
System.out.println("java.lang.reflect.Method类API");
System.out.println("------------------------------");
//getDeclaredMethods:获取本类中的所有方法
Method[] declaredMethods = c1.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println("本类中的所有方法="+declaredMethod.getName()+" 该方法的属性值="+declaredMethod.getModifiers()+" 该方法的返回类型="+declaredMethod.getReturnType());
//方法的形参类型
Class[] parameterTypes = declaredMethod.getParameterTypes();
for (Class parameterType : parameterTypes) {
System.out.println("形参类型= "+parameterType);
}
}
System.out.println("------------------------------");
System.out.println("java.lang.reflect.Constructor类API");
System.out.println("------------------------------");
//getDeclaredConstructors:获取本类中的所有构造器
Constructor[] declaredConstructors = c1.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println("本类中的所有构造器= "+declaredConstructor.getName()+" 该构造器的属性值= "+declaredConstructor.getModifiers());
Class[] parameterTypes = declaredConstructor.getParameterTypes();
for (Class parameterType : parameterTypes) {
System.out.println("形参类型= "+parameterType);
}
}
}}
class Student {
//属性
int age;
public String name;
private String grade;
protected static double score;
//方法
public void m1(int age ,String name,double score){
}
protected String m2(){
return null;
}
void m3(){
}
private void m4(){
}
//构造方法
Student() {
}
public Student(int age) {
this.age = age;
}
private Student(int age, String name, String grade) {
this.age = age;
this.name = name;
this.grade = grade;
}
}
反射爆破
反射创建对象
通过public的无参构造器创建实例
Object o = c3.newInstance();
通过pulic的有参构造创建实例
Constructor constructor = c3.getConstructor(String.class); //先得到构造器
Object tana = constructor.newInstance("tana"); //创建实例,传入实参
通过非public的有参构造器创建对象
setAccessible爆破
Constructor declaredConstructor = c3.getDeclaredConstructor(int.class,String.class); //先得到构造器
declaredConstructor.setAccessible(true); //爆破访问private构造器/方法/属性
Object mumu = declaredConstructor.newInstance(100, "mumu"); //创建实例,传入实参
package Sentiment.refelction;
import java.lang.reflect.Constructor;
public class ReflectionCreate {
public static void main(String[] args) throws Exception {
//获取类的Class对象
Class<?> c3 = Class.forName("Sentiment.refelction.User");
//通过public的无参构造器创建实例
Object o = c3.newInstance();
System.out.println(o);
//通过pulic的有参构造创建实例
Constructor constructor = c3.getConstructor(String.class);
Object tana = constructor.newInstance("tana");
System.out.println("tana = "+tana);
//通过非public的有参构造器创建对象
Constructor<?> declaredConstructor = c3.getDeclaredConstructor(int.class,String.class);
declaredConstructor.setAccessible(true);
Object mumu = declaredConstructor.newInstance(100, "mumu");;
System.out.println("mumu = "+mumu);
}
}
class User{
//属性
private int age=10;
private String name="Sentiment";
//构造方法
public User() {
}
public User(String name) {
this.name = name;
}
private User(int age, String name) {
this.age = age;
this.name = name;
}
public String toString() {
return "User{" + "age=" + age + ", name='" + name + '\'' + '}';
}
}
User{age=10, name='Sentiment'}
tana = User{age=10, name='tana'}
mumu = User{age=100, name='mumu'}
获取public属性
Field age = c4.getField("age"); //age为属性名
age.set(o,100); //修改属性值;o为对象实例
System.out.println(age.get(o));
获取属性:Class类对象.getField("属性值"); 修改属性值:属性.set(o,值); 输出属性值:属性.get(o); 获取private属性
Field name = c4.getDeclaredField("name"); //name为属性名
name.setAccessible(true); //爆破
name.set(o,"tana"); //修改属性值,o为对象实例
System.out.println(name.get(null)); //static修饰的对象,也可以用null代替
获取属性: Class类对象.getDeclaredField("属性值"); 爆破:属性.setAccessible(true);
实例代码:ReflectionCreate02.java
package Sentiment.refelction;
import java.lang.reflect.Field;
public class ReflectionCreate02 {
public static void main(String[] args) throws Exception{
Class c4 = Class.forName("Sentiment.refelction.human");
Object o = c4.newInstance();
//获取public属性
Field age = c4.getField("age");
age.set(o,100); //修改属性值
System.out.println(age.get(o));
//获取private属性
Field name = c4.getDeclaredField("name");
name.setAccessible(true);
name.set(o,"tana"); //修改属性值
System.out.println(name.get(null));
}
}
class human{
//属性
public int age=10;
private static String name ="Sentiment";
//构造器
public human() {
}
@Override
public String toString() {
return "human{" + "age=" + age +", name"+name+'}';
}
}
100
tana
反射调用方法
调用public方法
Method say1 = c5.getMethod("say1", String.class); //say1为String类型的方法
say1.invoke(o,"Sentiment");
获取方法:Class类对象.getMethod("方法名", 方法类型.class);; 调用方法:对象.invoke(实例化对象,"实参值"); 调用private方法
Method say2 = c5.getDeclaredMethod("say2", int.class, String.class, char.class); //say2方法及其类型
say2.setAccessible(true);
System.out.println(say2.invoke(o,10,"tana",'M'));
获取方法: Class类对象.getDeclaredMethod("方法名", 方法类型.class);; 调用方法:对象.invoke(实例化对象,"实参值"); 爆破:method.setAccessible(true);
实例代码:ReflectionCreate03.java
package Sentiment.refelction;
import java.lang.reflect.Method;
public class ReflectionCreate03 {
public static void main(String[] args) throws Exception{
Class c5 = Class.forName("Sentiment.refelction.man");
Object o = c5.newInstance();
//调用public方法
Method say1 = c5.getMethod("say1", String.class);
say1.invoke(o,"Sentiment");
//调用private方法
Method say2 = c5.getDeclaredMethod("say2", int.class, String.class, char.class);
say2.setAccessible(true);
System.out.println(say2.invoke(o,10,"tana",'M'));
System.out.println(say2.invoke(null,20,"mumu",'M')); //静态方法可以用null代替实例对象
}
}
class man{
//属性
public int age;
private static String name;
//构造方法
public man() {
}
//方法
public void say1(String a){
System.out.println("this is =>"+a);
}
private static String say2(int a,String b, char c){
return a+" "+b+" "+c;
}
}
反射练习
Work1
定义个Test类,其中定义私有属性name,赋值为"xxxxxx" Test类中创建公有方法getName()内容为return name 创建Test的Class类,并获得私有属性name,修改私有属性name的值,并调用getName()方法输出name的值
参考
package Sentiment.refelction;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Work1 {
public static void main(String[] args) throws Exception{
Class c1 = Class.forName("Sentiment.refelction.Test");
Object o = c1.newInstance();
Field name = c1.getDeclaredField("name");
name.setAccessible(true);
name.set(o,"tana");
Method getName = c1.getMethod("getName");
System.out.println(getName.invoke(o));
}
}
class Test{
private String name = "Sentiment";
public String getName(){
return name;
}
}
Work2
获取java.io.File的class对象,并输出该类的所有构造器方法 通过newInstance创建File对象,在自己电脑中创建个a.txt
参考
package Sentiment.refelction;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class Work2 {
public static void main(String[] args) throws Exception{
Class c2 = Class.forName("java.io.File");
Constructor[] c = c2.getDeclaredConstructors();
for (Constructor Constructor : c) {
System.out.println(Constructor);
}
//获取构造器public java.io.File(java.lang.String)
Constructor declaredConstructor = c2.getDeclaredConstructor(String.class);
String path="D:\\a.txt";
//实例化类
Object path1 = declaredConstructor.newInstance(path);
//获取createNewFile方法
Method createNewFile = c2.getMethod("createNewFile");
createNewFile.invoke(path1);
System.out.println(path1.getClass());
System.out.println("创建文件成功:"+path);
}
}
往期推荐