JAVA反射机制学习笔记
基本概念
通过java中的反射机制可以操作字节码文件。class文件。
(有点类似于黑客,可以读和修改字节码文件。)
相关类介绍
相关类在java.lang.reflect.* 包下。
常用类
java.lang.Class 代表整个字节码。代表一个类型。
java.lang.reflect.Method 代表字节码文件中的方法字节码。
java.lang.reflect.Constructor 代表字节码中的构造方法字节码。
java.lang.reflect.Field 代表字节码中的属性字节码。(代表类中的成员变量和实例变量–即堆内存中的变量/方法)
反射机制—通过 forName 创建类对象
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
// 反射机制---通过 forName 创建类对象
public class IO_StreamTest {
public static void main(String[] args) {
InputStream reader =Thread.currentThread().getContextClassLoader().getResourceAsStream("b.properties"); //起点是类的根路径下src下
Properties pro=new Properties();
try {
pro.load(reader);
} catch (IOException e) {
e.printStackTrace();
}
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
String classname=pro.getProperty("className");
System.out.println(classname);
Class c= null;
try {
c = Class.forName(classname); // 这个操作会导致类加载。类的静态代码块会执行。
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Object obj= null;
try {
obj = c.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
System.out.println(obj);
}
}
通过反射机制+properties配置文件创建对象
这种方式创建对象将更加灵活,更改properties配置文件,对象随之改变。
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
//使用反射机制+配置文件创建对象
public class Reflect_Test { //使用反射机制创建对象,只需改配置文件 (当前b.properties内容是 java.util.Date; 更改b.properties内容,创建的类对象也发生改变)。
public static void main(String[] args) {
FileReader reader= null;
try {
// reader = new FileReader("src/Java_bilibili/Class_Test/properties"); //idea 下可以这么写,但是不如下面的写法,因为下面的写法可以移植。
//通用路径写法 文件必须在src路径下面
String path=Thread.currentThread().getContextClassLoader().getResource("b.properties").getPath(); //起点是类的根路径下,也即src下。
System.out.println(path);
reader = new FileReader(path); //idea 下这么写
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Properties pro=new Properties();
try {
pro.load(reader);
} catch (IOException e) {
e.printStackTrace();
}
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
String classname=pro.getProperty("className");
Class c= null;
try {
c = Class.forName(classname); // 这个操作会导致类加载。类的静态代码块会执行。
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Object obj= null;
try {
obj = c.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
System.out.println(obj);
}
}
反射机制–访问类的属性
//反编译 Class 文件主代码
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class ReflectTest {
public static void main(String[] args) throws Exception{
Class stuclass=Class.forName("Java_bilibili.Reflect_Test.Filed.Stu"); //获取class文件-------这个路径是相对于src路径下的路径
Field[] fileds=stuclass.getFields(); //属性, 这里只能获取public 公开属性
System.out.println(fileds.length); // 长度为2,获取到了int 和 double 两个属性
for(Field f:fileds){
System.out.println(f.getType().getName());
System.out.println(f.getName());
}
Field[] fs2=stuclass.getDeclaredFields(); //获取所有属性
System.out.println(fs2.length);
for(Field f:fs2){
System.out.println(Modifier.toString(f.getModifiers()));
System.out.println(f.getType().getName());
System.out.println(f.getName());
}
}
}
//Stu类
public class Stu {
//Field 翻译为字段,其实就是属性/成员
//
public int no;
private String name;
protected int age;
boolean sex;
public static final double PI=3.1415926;
}
//反射机制获取Class属性
import java.lang.reflect.Field;
public class Test_2 {
public static void main(String[] args) throws Exception{
Class stuclass=Class.forName("Java_bilibili.Reflect_Test.Filed.Stu"); //可传入java自带的类和 src路径下的类
Object obj=stuclass.newInstance();
Field noField=stuclass.getDeclaredField("no"); //访问一个属性
noField.set(obj,2222);
System.out.println(noField.get(obj));
Field noField2=stuclass.getDeclaredField("name"); //访问一个私有属性
noField2.setAccessible(true); //打破封装后 方能赋值 //这个也是缺点,可能会给不法分子留下机会。
noField2.set(obj,"jark");
}
}
反射机制–反编译输出类中所有方法
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
//反编译输出--类中的所有方法
public class Decompile_Method {
public static void main(String[] args) throws ClassNotFoundException {
StringBuilder s=new StringBuilder();
Class x=Class.forName("java.util.HashSet"); //这个可以传入可变的配置文件
s.append(Modifier.toString(x.getModifiers())+"class "+"{"+x.getSimpleName()+"}");
Method[] methods=x.getDeclaredMethods(); //methods :类中的方法列表
for(Method m:methods){
s.append("\t");
s.append(Modifier.toString( m.getModifiers()));
s.append(" ");
s.append(m.getReturnType().getSimpleName());
s.append(" ");
s.append(m.getName());
s.append("(");
Class[] parameterTypes =m.getParameterTypes();
for(Class parameterType:parameterTypes){
s.append(parameterType.getSimpleName());
s.append(",");
}
s.deleteCharAt(s.length()-1);
s.append("){}\n");
}
s.append("}");
System.out.println(s);
}
}
反射机制–获取父类
//反射机制--获取父类
public class Get_superClass {
public static void main(String[] args) throws Exception{
Class stringClass=Class.forName("java.lang.String");
Class superClass=stringClass.getSuperclass();
System.out.println(superClass.getName());
Class[] interfaces=stringClass.getInterfaces(); //获取接口
for(Class in :interfaces){
System.out.println(in.getName());
}
}
}
最后,附上npy沙雕的日常。