反射机制
1.反射机制有什么用?
通过java语言反射机制可以操作字节码文件。
优点类似黑客,可以读和改写字节码文件
2.反射机制相关类都在java.lang.reflect.*;
3.反射机制相关重要类
java.lang.Class代表i字节码文件。
java.lang.reflect.Method代表字节码中方法字节码
java.lang.reflect.Constructor代表字节码中构造方法字节码
java.lang.reflect.Field代表字节码中成员变量字节码(静态变量和实例变量)
4.获取字节码的三种方式:
1.Class c=Class.forName("完整类名带包名")
2.Class c1=对象.getClass();
3.Class c2=任何类型.class;
package Reflect; public class ReflectText01 { //要操作一个字节码首先要找到这个类的字节码,怎么获取java.long.Class实例? // 三种方式 //1.Class c=Class.forName("完整类名带包名") //2.Class c1=对象.getClass(); //3.Class c2=任何类型.class; public static void main(String[] args) { /*Class.forName() 1.静态方法 2.方法的参数是一个字符串 3.完整类名必须带有包名。java.long包也不能忽略。 */
java中每个对象里都有getClass()方法
Class c1=null; Class c2=null; try { c1=Class.forName("完整类名带包名"); int []a=new int[1]; c2=a.getClass(); Class c3=int.class; } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } }
指向是都是方法区,存储都都是地址,‘==’
5.反射机制可以创建对象(重要)
那我们为什么不直接new一个对象呢?显然,它一定有存在的道理,它有着很强的耦合性,极大提高了程序的灵活度,遵循ocp原则!---框架
package Reflect; import java.io.FileReader; import java.util.Properties; public class ReflectText02 { public static void main(String[] args) throws Exception{ /*通过IO流读取.properties文件 优点:通过文件存储,不需要再更改代码,提高程序耦合性 */ FileReader reader=new FileReader("D:\\java\\javatext\\text.txt"); //创建属性类对象Map Properties p=new Properties();//(String key,String value)key=value //加载reader p.load(reader); //关闭 reader.close(); //通过key获取value String s=p.getProperty("className"); //通过反射机制实例化对象 Class a=Class.forName(s); Object o=a.newInstance(); System.out.println(o); } }
配置文件如下:
顺便回顾一下配置文件注意事项:
静态代码块在类加载时执行!!!!
package Reflect; public class User {
//静态代码块 static { System.out.println("这是一个静态代码块!!!!!!!!!!"); } User(){ System.out.println("这是一个user类!!!!!!!!!"); } public static void main(String[] args) { try { Class.forName("Reflect.User");//字节码文件 } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } }
6.聊聊路径:(重要)
补充一下:想要找到绝对路径必须将文件放在src类路径目录下,必须是直接的,中间不能有目录包含。不然找不到..
伪代码:
这种方式获取的绝对路径是通用的
这样写,以后文件在类路径下也就是src下的文件都可以被找到,即使更换了路径,即使不用windows系统,它依然可以被找到,很牛逼,提高了程序的耦合性
第二种写法:
第三种:(推荐)
7.使用资源绑定器
资源绑定器:只能绑定xxx.properties文件,并且这个文件必须在类路径下。并且在写路径的时候,路径后面的扩展名不能写、
package Reflect; import java.io.IOException; import java.io.InputStream; import java.util.Properties; import java.util.ResourceBundle; public class User { public static void main(String[] args) { //资源绑定器 ResourceBundle r=ResourceBundle.getBundle("text02");//不能带.properties后缀!!!!!!!!!! String s1=r.getString("className"); System.out.println(s1); } }
ps:还是得在src目录下面
8.双亲委派机制(了解)
//启动是父,扩展是母。这样避免了有人篡改数据。
9.1反射--Filed(属性)类
常用方法:
String s2=a.getName();//获取完整类名
String f1=a.getSimpleName();//获取简类名
Field[] fields=a.getFields();////Fields只能获取权限为公共的属性
Field[] fields1=a.getDeclaredFields();//DeclaredFields这个是获取所有属性
Field f=fields[0];//第一个属性
String fName=f.getName();//得到属性名
Class aClass=f.getType();//获取类型名
int t=f.getModifiers();
String sm=Modifier.toString(t);//能将int转为String
Modifier(修饰符)中toString能将int转换为String
package Reflect; import java.lang.reflect.Field; import java.lang.reflect.Modifier; //Field(属性) public class ReflectText03 { public static void main(String[] args) throws Exception{ //获取类 Class a=Class.forName("Student"); String s2=a.getName();//获取完整类名 String f1=a.getSimpleName();//获取简类名 Field[] fields=a.getFields();////Fields只能获取权限为公共的属性 Field[] fields1=a.getDeclaredFields();//DeclaredFields这个是获取所有属性 Field f=fields[0];//第一个属性 String fName=f.getName();//得到属性名 Class aClass=f.getType();//获取类型名 int t=f.getModifiers();//返回的是数字,每个修饰符都有数字代号!! String sm=Modifier.toString(t);//能将int转为String System.out.println(s2); } }
1.通过反射机制访问对象属性
.set(对象,修改值)
9.2反射--Method(方法)类(重要!!)
2.1可变长参数(重点)
语法:类型...args
1,(参数随便取,3个点)
2,可变长参数在参数列表中只能存在一个并且要放到最后
3,可变长参数可以当一个数组(能用.lenth)
2.2.Method类
常用方法:
Modifier.toString(c1.getModifiers()//获取修饰符(记得转tostring)
m.getReturnType().getSimpleName();//获取返回值类型的简类名
m.getName();//获取名字
Class[] pt=m.getParameterTypes();//获取数据类型
//获取参数 for (Class c:pt) {System.out.println(c.getSimpleName();}
2.3通过反射机制调用对象属性并修改(主要使用到了属性的set()方法)
package Reflect; import java.lang.reflect.Method; import java.lang.reflect.Modifier; public class ArgsText { public static void main(String[] args) throws Exception{ Class c1=Class.forName("Reflect.User"); Method[] a=c1.getDeclaredMethods(); for (Method m:a ) { System.out.println(Modifier.toString(c1.getModifiers()));//获取修饰符(记得转tostring) System.out.println(m.getReturnType().getSimpleName());//获取返回值类型的简类名 System.out.println(m.getName());//获取名字 Class[] pt=m.getParameterTypes();//获取数据类型 //获取参数 for (Class c:pt ) { System.out.println(c.getSimpleName()); } } } public static void m(int...args){ System.out.println("m方法执行了!!!"); } }
2.4通过反射机制调用方法(获取返回值)
类、对象、方法【实参】、返回值package Reflect;
import java.lang.reflect.Method; public class MethodText01 { public static void main(String[] args) throws Exception{ Class aClass=Class.forName("Student");//获取类 Object obj=aClass.newInstance();//获取对象 //四要素: /* Method方法 obj对象 “lengbo”,“123” 实参 retvalue 返回值 */
//(方法名,形参类型.class......【可以是n个】)
Method method=aClass.getDeclaredMethod("logn",String.class,String.class);//获取方法、实参 Object o=method.invoke(obj,"lengbo","wjn12345");//获取返回值(获取对象,实参列表...【可以n个】) System.out.println(o); } }
9.3反射--Constructer类(构造方法)
还是:类,对象,构造方法(构造方法也是可以n个参数)
package Reflect; import java.lang.reflect.Constructor; public class ReflectConstructertext01 { public static void main(String[] args) throws Exception{ Class c=Class.forName("Student");//获取类 Object obj=c.newInstance();//获取对象 System.out.println(obj); Constructor constructor=c.getDeclaredConstructor();//获取无参构造方法 Object o1=constructor.newInstance();//调用无参时的方法 System.out.println(o1); Constructor constructor1=c.getDeclaredConstructor(int.class,String.class);//获取有参构造方法 Object o2=constructor1.newInstance(10,"lengbo");//调用有参时方法 System.out.println(o2); } }
9.4反射--获取反射对象的实现的接口与继承的父类
一样,类,对象,接口,super(父类)
package Reflect; public class extendsReflecttext01 { public static void main(String[] args) throws Exception{ Class c=Class.forName("java.lang.String"); Class superc=c.getSuperclass();//获取String的父类 System.out.println(superc.getSimpleName()); Class []interfaces=c.getInterfaces();//获取String的实现接口 for (Class i: interfaces) { System.out.println(i.getName()); } } }
反射到这里就结束了,你很厉害,加油!