作者:云彩熨衣裳 | 来源:互联网 | 2024-10-10 13:53
小白进阶之反射学习(超详细)-1什么是反射?Reflection(反射)是Java程序开发语言的特征之一,它允许运行中的Java程序对自身进行检查,或者说“自审”,也有称
1 什么是反射?
Reflection(反射) 是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,或者说“自审”,也有称作“自省”。
反射非常强大,它甚至能直接操作程序的私有属性。我们前面学习都有一个概念,被private封装的资源只能类内部访问,外部是不行的,但这个规定被反射赤裸裸的打破了。
反射就像一面镜子,它可以在运行时获取一个类的所有信息,可以获取到任何定义的信息(包括成员变量,成员方法,构造器等),并且可以操纵类的字段、方法、构造器等部分。
2 为什么需要反射?
如果想创建对象,我们直接new User(); 不是很方便嘛,为什么要去通过反射创建对象呢?
那我要先问你个问题了,你为什么要去餐馆吃饭呢?
例如:我们要吃个牛排大餐,如果我们自己创建,就什么都得管理。
好处是,每一步做什么我都很清晰,坏处是什么都得自己实现,那不是累死了。牛接生你管,吃什么你管,屠宰你管,运输你管,冷藏你管,烹饪你管,上桌你管。就拿做菜来说,你能有特级厨师做的好?
那怎么办呢?有句话说的好,专业的事情交给专业的人做,饲养交给农场主,屠宰交给刽子手,烹饪交给特级厨师。那我们干嘛呢?
我们翘起二郎腿直接拿过来吃就好了。
再者,饭店把东西做好,不能扔到地上,我们去捡着吃吧,那不是都成原始人了。那怎么办呢?很简单,把做好的东西放在一个容器中吧,如把牛排放在盘子里。
我们在后面的学习中,会学习框架,有一个框架Spring就是一个非常专业且功能强大的产品,它可以帮我们创建对象,管理对象。以后我无需手动new对象,直接从Spring提供的容器中的Beans获取即可。Beans底层其实就是一个Map,最终通过getBean(“user”)来获取。而这其中最核心的实现就是利用反射技术。
总结一句,类不是你创建的,是你同事或者直接是第三方公司,此时你要或得这个类的底层功能调用,就需要反射技术实现。有点抽象,别着急,我们做个案例,你就立马清晰。
3 反射需要用到的API
3.1 获取字节码对象
Class.forName(“类的全路径”);
类名.class
对象.getClass();
3.2 常用方法
获取包名 类名
clazz.getPackage().getName()//包名
clazz.getSimpleName()//类名
clazz.getName()//完整类名
获取成员变量定义信息
getFields()//获取所有公开的成员变量,包括继承变量
getDeclaredFields()//获取本类定义的成员变量,包括私有,但不包括继承的变量
getField(变量名)
getDeclaredField(变量名)
获取构造方法定义信息
getConstructor(参数类型列表)//获取公开的构造方法
getConstructors()//获取所有的公开的构造方法
getDeclaredConstructors()//获取所有的构造方法,包括私有
getDeclaredConstructor(int.class,String.class)
获取方法定义信息
getMethods()//获取所有可见的方法,包括继承的方法
getMethod(方法名,参数类型列表)
getDeclaredMethods()//获取本类定义的的方法,包括私有,不包括继承的方法
getDeclaredMethod(方法名,int.class,String.class)
反射新建实例
clazz.newInstance();//执行无参构造创建对象
clazz.newInstance(666,”海绵宝宝”);//执行含参构造创建对象
clazz.getConstructor(int.class,String.class)//获取构造方法
反射调用成员变量
clazz.getDeclaredField(变量名);//获取变量
clazz.setAccessible(true);//使私有成员允许访问
f.set(实例,值);//为指定实例的变量赋值,静态变量,第一参数给null
f.get(实例);//访问指定实例变量的值,静态变量,第一参数给null
反射调用成员方法
Method m = Clazz.getDeclaredMethod(方法名,参数类型列表);
m.setAccessible(true);//使私有方法允许被调用
m.invoke(实例,参数数据);//让指定实例来执行该方法
4 反射的应用
4.1 创建 : 测试物料类
创建包: cn.tedu. reflection
创建类: Student.java
package cn.tedu.reflection;
public class Student {
String name;
int age;
public Student() {}
public Student(String name,int age) {
super();
this.name = name;
this.age = age;
}
public void eat(int n) {
System.out.println("饿了吃点火锅吧"+n);
}
@Override
public String toString() {
return "Student [name="+ name +",age="+ age +"]";
}
}
4.2 练习 : 获取类对象
创建包: cn.tedu. reflection
创建类: Test1Reflect.java
package cn.tedu.reflection;
import java.lang.reflect.Constructor;
import java.util.Arrays;
import org.junit.Test;
public class Test1Reflect {
@Test
public void getClazz() throws Exception {
Class<?> student1 = Class.forName("cn.tedu.reflection.Student");
Class<?> student2 = Student.class;
Class<?> student3 = new Student().getClass();
System.out.println(student1);
System.out.println(student2.getName());
System.out.println(student3.getSimpleName());
System.out.println(student3.getPackage().getName());
}
}
4.3 练习 : 类获取构造方法
package cn.tedu.reflection;
import java.lang.reflect.Constructor;
import java.util.Arrays;
import org.junit.Test;
public class Test1Reflect {
@Test
public void getConstruct() {
Class<?> clazz = Student.class;
Constructor<?>[] cs = clazz.getConstructors();
for (Constructor c : cs) {
System.out.println(c.getName());
Class[] cp = c.getParameterTypes();
System.out.println(Arrays.toString(cp));
}
}
}
4.4 练习 : 获取成员方法
package cn.tedu.reflection;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.junit.Test;
public class Test1Reflect {
@Test
public void getFunction() throws Exception {
Class<?> clazz = Class.forName("cn.tedu.reflection.Student");
Method[] ms = clazz.getMethods();
for (Method m : ms) {
System.out.println(m.getName());
Class<?>[] pt = m.getParameterTypes();
System.out.println(Arrays.toString(pt));
}
}
}
4.5 练习 : 获取成员变量
package cn.tedu.reflection;
import java.lang.reflect.Field;
import org.junit.Test;
public class Test1Reflect {
@Test
public void getFields(){
Class<?> clazz = Student.class;
Field[] fs = clazz.getFields();
for (Field f: fs) {
System.out.println(f.getName());
System.out.println(f.getType().getName());
}
}
}
4.6 练习 : 创建对象
package cn.tedu.reflection;
import java.lang.reflect.Constructor;
import org.junit.Test;
public class Test1Reflect {
@Test
public void getObject () throws Exception {
Class<?> clazz = Student.class;
Object obj = clazz.newInstance();
System.out.println(obj);
Constructor<?> c = clazz.getConstructor(String.class,int.class);
Object obj2 = c.newInstance("海绵宝宝",3);
System.out.println(obj2);
Student s = (Student)obj2;
System.out.println(s.name);
System.out.println(s.age);
s.eat(666);
}
}
4.7 熟悉API
自己创建类练习,获取类中的所有资源,熟悉反射中涉及的API
5 暴力反射
指可以将程序中的私有的属性或者方法通过反射技术,暴力的获取到资源。需要使用的常见方法如下:
5.1 创建 : 测试物料类
创建包: cn.tedu. reflection
创建类: Person.java
package cn.tedu.reflection;
public class Person {
private String name;
private int age;
private void save(int m,String n) {
System.out.println("save().."+m+n);
}
private void update() {
System.out.println("update()..");
}
}
5.2 练习 : 创建测试类
创建包: cn.tedu. reflection
创建类: TestReflect2.java
package cn.tedu.reflection;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.junit.Test;
public class TestReflect2 {
@Test
public void getField() throws Exception {
Class<?> clazz = Person.class;
Field field = clazz.getDeclaredField("name");
System.out.println(field.getType().getName());
Object obj = clazz.newInstance();
field.setAccessible(true);
field.set(obj, "派大星");
System.out.println(field.get(obj));
}
@Test
public void getFunction() throws Exception{
Class<?> clazz = Person.class;
Method method = clazz.getDeclaredMethod("save", int.class,String.class);
Object obj = clazz.newInstance();
method.setAccessible(true);
method.invoke(obj, 100,"蟹老板");
}
}
恭喜你,又学会了一个新知识,反射的API比较多,要多多练习哦
下一节 内部类 点这里哦