java-反射精讲

一、反射是什么

反射即是获取类信息的一种能力!,把某个类的方法,变量,构造器全部获取到,然后加以应用!

二、用反射方法获取类信息

1.首先我们准备好各个类与接口

//Cat 类

java 复制代码
public class Cat implements jump,Run {
    public int age;
    private String name;
    protected String color;
    double height;
	public Cat(int age, String name, String color, double height) {
		super();
		this.age = age;
		this.name = name;
		this.color = color;
		this.height = height;
	}
    Cat(){
    	
    }
    Cat(String color){
    	this.color=color;
    }
    public void run(String name,int age,double height) {
    	System.out.println("小猫的名字叫:"+name);
    }
    
    public void run(String name) {
    	System.out.println("小猫的名字叫"+name);
    }
    
    private int setAge(int age) {
    	System.out.println("aa"+age);
    	return age;
    }
    void fly() {
    	System.out.println("猫不会飞");
    }
    
    protected void jump(int num) {
    	System.out.println("猫能跳"+num+"米");
    }
}

// Run与jump接口

java 复制代码
public interface Run {

}
java 复制代码
public interface jump {

}

创建一个Test类!(接下来我将带领你领略反射的魔力!

java 复制代码
public class Testt {
        
}

2.获取类(Cat)信息

(1)要想使用反射,就必须先生成类对象

一个类的编译过程

获取类对象有三种方法

java 复制代码
public class Testt {
	public static void main(String[] args)  throws Exception {
		Cat cat=new Cat("black");
		Class class1=cat.getClass();//方法1
		Class class2=Cat.class;//方法2
		Class class3=Class.forName("com.qcby.反射.Cat");//方法3  类的路径
		System.out.println(class1);
		System.out.println(class2);
		System.out.println(class2);
	}
}

结果:

说明这三种方法是等价的!!!我们获取到了类信息,以变量class1 class2 class3 变量展示

3.获取类的修饰符

类信息存储的形式一般有两种:1.获取相关的集合,2.直接获取

(1)获取相关的集合
java 复制代码
import java.lang.reflect.Field;
import java.util.Arrays;
public class Testt {
	public static void main(String[] args)  throws Exception {
		Cat cat=new Cat("black");
		Class class1=cat.getClass();//方法1
		Class class2=Cat.class;//方法2
		Class class3=Class.forName("com.qcby.反射.Cat");//方法3  类的路径
		
		Field[] fields=class3.getDeclaredFields();
		System.out.println(Arrays.toString(fields));
	}
}

输出如果:

我们获取到了Cat的所有修饰符

如果我们将class3.getDeclaredFields()改成class3.getFields()呢?

所以我们可以看到访问修饰符是 添加Declared可以访问到所有的修饰符(包括private public protected..) 而去掉 Declared只能访问到public 修饰符!

(2)直接获取
java 复制代码
import java.lang.reflect.Field;
import java.util.Arrays;
public class Testt {
	public static void main(String[] args)  throws Exception {
		Cat cat=new Cat("black");
		Class class1=cat.getClass();//方法1
		Class class2=Cat.class;//方法2
		Class class3=Class.forName("com.qcby.反射.Cat");//方法3  类的路径
		
		Field ageField= class3.getDeclaredField("age");
		Field nameField= class3.getDeclaredField("name");
		Field colorField= class3.getDeclaredField("color");
		Field heightField= class3.getDeclaredField("height");
		System.out.println(ageField);
		System.out.println(nameField);
		System.out.println(colorField);
		System.out.println(heightField);
	}
}

结果:

注意:1.当访问private和protected修饰符时,不用Declared就会报错!

2.两种获取类信息的方法我已介绍完毕,后文我将直接使用不再介绍

4.获取类方法:
java 复制代码
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
public class Testt {
	public static void main(String[] args)  throws Exception {
		Cat cat=new Cat("black");
		Class class1=cat.getClass();//方法1
		Class class2=Cat.class;//方法2
		Class class3=Class.forName("com.qcby.反射.Cat");//方法3  类的路径
		
		Field ageField= class3.getDeclaredField("age");
		Field nameField= class3.getDeclaredField("name");
		Field colorField= class3.getDeclaredField("color");
		Field heightField= class3.getDeclaredField("height");
	   //获取方法
		Method[] methods= class3.getDeclaredMethods();
		System.out.println(Arrays.toString(methods));
		Method[] methods1=class3.getMethods();
		System.out.println(Arrays.toString(methods1));
		Method run1 = class3.getDeclaredMethod("run",String.class);
		System.out.println(run1);
		Method run2 = class3.getMethod("run", String.class);
		System.out.println(run2);
		Method fly= class3.getDeclaredMethod("fly");
		System.out.println(fly);
	}
}

结果:

4.获取构造器:
java 复制代码
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.util.Arrays;
public class Testt {
	public static void main(String[] args)  throws Exception {
		Cat cat=new Cat("black");
		Class class1=cat.getClass();//方法1
		Class class2=Cat.class;//方法2
		Class class3=Class.forName("com.qcby.反射.Cat");//方法3  类的路径
		
		Field ageField= class3.getDeclaredField("age");
		Field nameField= class3.getDeclaredField("name");
		Field colorField= class3.getDeclaredField("color");
		Field heightField= class3.getDeclaredField("height");
	   //获取方法
		Method[] methods= class3.getDeclaredMethods();

		Method[] methods1=class3.getMethods();

		Method run1 = class3.getDeclaredMethod("run",String.class);

		Method run2 = class3.getMethod("run", String.class);
	
		Method fly= class3.getDeclaredMethod("fly");

		//获取构造器
       
	    Constructor[] c1 = class3.getDeclaredConstructors();
	    System.out.println(Arrays.toString(c1));
	    Constructor[] c2 =class3.getConstructors();
	    System.out.println(Arrays.toString(c2));
	    Constructor c3 =class3.getDeclaredConstructor(String.class);
	    System.out.println(c3);
	}
}

5.获取接口

java 复制代码
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.util.Arrays;
public class Testt {
	public static void main(String[] args)  throws Exception {
		Cat cat=new Cat("black");
		Class class1=cat.getClass();//方法1
		Class class2=Cat.class;//方法2
		Class class3=Class.forName("com.qcby.反射.Cat");//方法3  类的路径
		
		Field ageField= class3.getDeclaredField("age");
		Field nameField= class3.getDeclaredField("name");
		Field colorField= class3.getDeclaredField("color");
		Field heightField= class3.getDeclaredField("height");
	   //获取方法
		Method[] methods= class3.getDeclaredMethods();

		Method[] methods1=class3.getMethods();

		Method run1 = class3.getDeclaredMethod("run",String.class);

		Method run2 = class3.getMethod("run", String.class);
	
		Method fly= class3.getDeclaredMethod("fly");

		//获取构造器
       
	    Constructor[] c1 = class3.getDeclaredConstructors();
	    
	    Constructor[] c2 =class3.getConstructors();

	    Constructor c3 =class3.getDeclaredConstructor(String.class);
	  //获取接口
       Class[] classes=class3.getInterfaces();
       System.out.println(Arrays.toString(classes));
	}
}

结果:

三、获取的类信息中的值

我们首先获取类的各个修饰符,其次获取他的构造方法,将获取 的构造方法赋值给变量,再让变量,强制转换为Cat类,看代码:

java 复制代码
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.util.Arrays;
public class Testt {
	public static void main(String[] args)  throws Exception {
		Cat cat=new Cat("black");
		Class class1=cat.getClass();//方法1
		Class class2=Cat.class;//方法2
		Class class3=Class.forName("com.qcby.反射.Cat");//方法3  类的路径
		
		Field ageField= class3.getDeclaredField("age");
		Field nameField= class3.getDeclaredField("name");
		Field colorField= class3.getDeclaredField("color");
		Field heightField= class3.getDeclaredField("height");
	   
		//获取构造器
       
		Constructor c1 =class3.getDeclaredConstructor(int.class,String.class,String.class,double.class);
	    
	    Constructor c2 =class3.getDeclaredConstructor(String.class);
     
        
        Cat cat1= (Cat) c1.newInstance(10,"小白","白色",10.44);//强制转换成Cat类!
        //获取cat1中修饰符的值
         System.out.println(ageField.get(cat1));
         System.out.println(nameField.get(cat1));
         System.out.println(colorField.get(cat1));
         System.out.println(heightField.get(cat1));
	}
}

运行结果:

我们成功的获取到了构造方法中的age的值,但是当我们获取name 的时候确保错了

这是因为在Cat类中,name 是由 private修饰的,当应用private修饰的修饰符以及方法时,我们要用到暴力反射

java 复制代码
 //获取cat1中修饰符的值
         System.out.println(ageField.get(cat1));
         nameField.setAccessible(true);//暴力反射
         System.out.println(nameField.get(cat1));
         System.out.println(colorField.get(cat1));
         System.out.println(heightField.get(cat1));

这样就允许我们去获取或者修改private 修饰的修饰符或者方法以及构造器了

输出结果:

四、设置类信息的值

java 复制代码
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.util.Arrays;
public class Testt {
	public static void main(String[] args)  throws Exception {
		Cat cat=new Cat("black");
		Class class1=cat.getClass();//方法1
		Class class2=Cat.class;//方法2
		Class class3=Class.forName("com.qcby.反射.Cat");//方法3  类的路径
		
		Field ageField= class3.getDeclaredField("age");
		Field nameField= class3.getDeclaredField("name");
		Field colorField= class3.getDeclaredField("color");
		Field heightField= class3.getDeclaredField("height");
	   
		Constructor c1 =class3.getDeclaredConstructor(int.class,String.class,String.class,double.class);
		Constructor c2 =class3.getDeclaredConstructor();
		Constructor c3 =class3.getDeclaredConstructor(String.class);
		Cat cat1= (Cat) c1.newInstance(10,"小白","白色",10.44);
		//暴力反射--->使用private修饰的数据
		c2.setAccessible(true);
		Cat cat2 = (Cat) c2.newInstance();
		Cat cat3 = (Cat) c3.newInstance("黑色");
		
		
        ageField.set(cat1, 100);
        int age1 = (int) ageField.get(cat1);
        System.out.println(age1);
        //暴力反射private修饰符
        nameField.setAccessible(true);
        nameField.set(cat1, "花花");
        System.out.println(nameField.get(cat1));
        System.out.println(colorField.get(cat1));
	}
}

xx.set(obj,各参数的值)便是设置值的语句

注意private 修饰的修饰符和方法,需要暴力反射哦~

相关推荐
洛_尘2 分钟前
Java EE进阶:Linux的基本使用
java·java-ee
无限进步_3 分钟前
【C++】电话号码的字母组合:从有限处理到通用解法
开发语言·c++·ide·windows·git·github·visual studio
宸津-代码粉碎机4 分钟前
Spring Boot 4.0虚拟线程实战调优技巧,最大化发挥并发优势
java·人工智能·spring boot·后端·python
MaCa .BaKa7 分钟前
47-心里健康咨询平台/心理咨询系统
java·spring boot·mysql·tomcat·maven·intellij-idea·个人开发
JJay.18 分钟前
Android Kotlin 协程使用指南
android·开发语言·kotlin
csbysj202024 分钟前
jQuery 捕获详解
开发语言
木子欢儿25 分钟前
Docker Hub 镜像发布指南
java·spring cloud·docker·容器·eureka
C++ 老炮儿的技术栈33 分钟前
GCC编译时无法向/tmp 目录写入临时汇编文件,因为设备空间不足,解决
linux·运维·开发语言·汇编·c++·git·qt
Devin~Y36 分钟前
高并发电商与AI智能客服场景下的Java面试实战:从Spring Boot到RAG与向量数据库落地
java·spring boot·redis·elasticsearch·spring cloud·kafka·rag
蜡台41 分钟前
IDEA 一些 使用配置和插件
java·ide·intellij-idea