反射机制
反射机制有什么用?
通过反射机制可以操作代码片段(class文件),可以让程序更加灵活
反射机制的相关类在哪个包下?
java.lang.reflect.*;
反射机制相关的重要的类有哪些?
java.lang.Class:代表整个字节码文件
java.lang.reflect.Method:代表字节码中的方法字节码
java.lang.reflect.Constructor:代表字节码中的构造方法字节码
java.lang.reflect.Field:代表字节码中的属性字节码,代表类中的成员变量(静态变量 + 实例变量)
获取Class的三种方式
第一种方式:
public static void main(String[] args) {
/*
Class.forName()
1.静态方法
2.方法的参数是一个字符串
3.字符串需要的是一个完整类名
4.完整类名必须带有包名,java.lang也不能省略
*/
Class c1 = null;
Class c2 = null;
try {
c1 = Class.forName("java.lang.String"); // c1代表String.class文件,或者说c1代表String类型
c2 = Class.forName("java.util.Date");// c2代表Date类型
Class c3 = Class.forName("java.lang.Integer");
Class c4 = Class.forName("java.lang.System");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
第二种方式:
//java中任何一个对象都有一个方法:getClass()
String s = "abc";
Class x = s.getClass(); // x代表String.class字节码文件,x代表String类型
System.out.println(c1 == x);// true( == 判断的是对象的内存地址)
Date time = new Date();
Class t = time.getClass();
System.out.println(t == c2);// true(c2和t中保存的内存地址都是一样的,都指向方法区当中的字节码文件)
第三种方式
//java语言中任何一种类型,他都有.class属性
Class a = String.class; //a代表String类型
Class b = Date.class;
Class c = int.class;
Class d = double.class;
System.out.println(a == x); //true
获取Class之后,可以调用无参数构造方法来实例化对象
public static void main(String[] args) {
try {
// 通过反射机制获取Class,通过Class来实例化对象
Class u = Class.forName("com.cedric.java.been.User");
// newInstance()这个方法会调用User这个类的无参数构造方法,完成对象的创建
// 重点:newInstance()调用的是无参构造,必须保证无参构造是存在的
Object o = u.newInstance();
System.out.println(o);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
注意:newInstance()方法内部实际上调用了无参构造方法,必须保证无参构造存在才可以
如果只想让一个类的“静态代码块”执行的话,可以这样
Class.forName("该类的类名"); 这样类就加载了,类加载的时候静态代码块执行!!
关于路径问题?
String path = Thread.currentThread().getContextClassLoader().
getResourse("写相对路径,但是这个相对路径从src触发开始找").getPath()
这种方式是为了获取一个文件的绝对路径(通用方式,不会受到环境移植的影响)
但是该文件要求放在类路径下,也就是放在src下,src是类的根路径
直接以流的形式返回:
InputStream in = Thread.currentThread().getContextClassLoader.
getResourseAsStream("com/cedric/test.properties");
IO + Properties,怎么快速绑定属性资源文件?
public static void main(String[] args) {
try {
// 代码是灵活的,不需要改动,可以修改配置文件,配置文件修改之后,可以创建出不同的实例对象
// 通过IO读取classinfo.properties文件
FileReader read = new FileReader("Reflex/classinfo.properties");
// 创建属性类对象Map
Properties pro = new Properties();
// 加载
pro.load(read);
// 关闭
read.close();
// 通过key获取value
String s = pro.getProperty("className");
// 通过反射机制实例化对象
Class c = Class.forName(s);
Object o = c.newInstance();
System.out.println(o);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
Filed
反射Student类中所有的Filed
public static void main(String[] args) {
// 获取整个类
try {
Class studentClass = Class.forName("com.cedric.java.been.Student");
//com.cedric.java.been.Student
String scName = studentClass.getName();
System.out.println("完整类名:" + scName);
// 简类名
String simpleName = studentClass.getSimpleName();
System.out.println("简类名:" + simpleName);
// 获取到所有的public修饰的Filed
Field[] files = studentClass.getFields();
System.out.println(files.length); // 测试数组中只有一个元素
// 取出这个Filed
Field fileds = files[0];
// 取出这个Field他的名字
String s = fileds.getName();
System.out.println(s);
// 获取所有的Field
Field[] fs = studentClass.getDeclaredFields();
System.out.println(fs.length); //4
System.out.println("====================");
// 遍历
for(Field field : fs){
// 获取属性的修饰符列表
int i = field.getModifiers(); // 返回的修饰符是一个数字,每一个数字是修饰符的代号
System.out.println(i);
// 将代号数字转换成字符串
String modifierString = Modifier.toString(i);
System.out.println(modifierString);
// 获取属性的类型
Class fieldType = field.getType();
//String fieldName = fieldType.getName();
String fieldName = fieldType.getSimpleName();
System.out.println(fieldName);
// 获取属性的名字
System.out.println(field.getName());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
反编译
通过反射机制,反编译一个类的属性Field
public static void main(String[] args) {
try {
StringBuilder s = new StringBuilder();
Class studentClass = Class.forName("com.cedric.java.been.Student");
s.append(Modifier.toString(studentClass.getModifiers()) + " " + "class" + " " + studentClass.getSimpleName() + "{" + '\n');
Field[] fields = studentClass.getDeclaredFields();
for(Field field : fields){
s.append('\t');
s.append(Modifier.toString(field.getModifiers()));
s.append(" ");
s.append(field.getType().getSimpleName());
s.append(" ");
s.append(field.getName());
s.append(";\n");
}
s.append("}");
System.out.println(s);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
反编译Method(反编译一个类的方法)
public static void main(String[] args) {
try {
StringBuilder s = new StringBuilder();
Class userServiceClass = Class.forName("com.cedric.java.been.UserService");
s.append(Modifier.toString(userServiceClass.getModifiers()) + " class " +userServiceClass.getSimpleName() + "{\n");
Method[] methods = userServiceClass.getDeclaredMethods();
for(Method method : methods){
s.append("\t");
s.append(Modifier.toString(method.getModifiers()));
s.append(" ");
s.append(method.getReturnType().getSimpleName());
s.append(" ");
s.append(method.getName());
s.append("(");
// 参数列表
Class[] parameterTypes = method.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);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
反编译Constructor
public static void main(String[] args) {
StringBuilder s = new StringBuilder();
try {
Class vipClass = Class.forName("com.cedric.java.been.Vip");
s.append(Modifier.toString(vipClass.getModifiers()));
s.append(" class ");
s.append(vipClass.getSimpleName());
s.append("{\n");
// 拼接构造方法
Constructor[] constructors = vipClass.getDeclaredConstructors();
for(Constructor constructor : constructors){
s.append("\t");
s.append(Modifier.toString(constructor.getModifiers()));
s.append(" ");
s.append(vipClass.getSimpleName());
s.append("(");
// 拼接参数
Class[] parameter = constructor.getParameterTypes();
for(Class parameterType : parameter){
s.append(parameterType.getSimpleName());
s.append(",");
}
if(parameter.length > 0){
// 删除最后下标位置上的字符
s.deleteCharAt(s.length() - 1);
}
s.append("){}\n");
}
s.append("}");
System.out.println(s);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
怎么通过反射机制访问一个java对象的属性?
// 使用反射机制,怎么去获取一个对象的属性(set get)
Class studentClass = Class.forName("com.cedric.java.been.Student");
Object obj = studentClass.newInstance(); // obj就是Student对象(底层调用无参数构造方法)
// 获取name属性
Field noFiled = studentClass.getDeclaredField("name");
// 给obj对象(Student对象)的name属性赋值
noFiled.set(obj,"zhangsan"); // 给obj对象的no属性赋值1111
// 读取属性的值
System.out.println(noFiled.get(obj));
//打破封装 反射机制访问java私有属性: noField.setAccessible(true);
Method
// 获取类
Class userServiceClass = Class.forName("com.cedric.java.been.UserService");
// 获取所有的Method(包括私有的)
Method[] methods = userServiceClass.getDeclaredMethods();
// 遍历Method
for(Method method : methods){
// 获取修饰符列表
System.out.println(Modifier.toString(method.getModifiers()));
// 获取方法的返回值类型
Class methodType = method.getReturnType();
System.out.println(methodType.getSimpleName());
// 获取方法名
System.out.println(method.getName());
// 方法的修饰符列表(一个方法的参数可能会有多个)
Class[] parameterType = method.getParameterTypes();
for(Class parameter : parameterType){
System.out.println(parameter.getSimpleName());
}
通过反射机制怎么调用一个对象的方法
public static void main(String[] args) {
/*
要素分析:
要素1:对象userService
要素2:login方法名
要素3:实参列表
要素4:返回值
*/
// 使用反射机制来调用一个对象的方法该怎么做
try {
Class userServiceClass = Class.forName("com.cedric.java.been.UserService");
// 创建对象
Object obj = userServiceClass.newInstance();
// 获取Method
Method loginMethod = userServiceClass.getDeclaredMethod("login",String.class,String.class);
//调用方法
// 反射机制中最重要的方法
/*
四要素:
loginMethod方法
obj对象
“admin”,“123”实参
retValue返回值
*/
Object retValue = loginMethod.invoke(obj,"admin","123");
System.out.println(retValue);
通过反射机制调用构造方法实例化java对象
try {
Class c = Class.forName("com.cedric.java.been.Vip");
// 调用无参构造
Object o = c.newInstance();
System.out.println(o);
// 调用有参数构造方法
// 第一步:先获取到这个有参数的构造方法
Constructor con = c.getDeclaredConstructor(int.class,String.class,String.class,boolean.class);
// 第二步,调用构造方法new对象
Object obj = con.newInstance(110,"Jack","2001-01-01",true);
System.out.println(obj);
// 获取无参构造方法
Constructor con1 = c.getDeclaredConstructor();
Object obj1 = con1.newInstance();
System.out.println(obj1);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
给你一个类,怎么获取这个类的父类,已经实现了哪些接口?
// String
try {
Class stringClass = Class.forName("java.lang.String");
// 获取String的父类
Class stringSuper = stringClass.getSuperclass();
System.out.println(stringSuper);
// 获取String类实现的所有接口
Class[] interfaces = stringClass.getInterfaces();
for(Class in : interfaces){
System.out.println(in.getName());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
资源绑定器
/*
java.util包下提供了一个资源绑定器,便于获取属性配置文件中的内容
使用以下这种方式的时候,属性配置文件xx.Properties必须放到类路径下
*/
public class ResourceBundleTest {
public static void main(String[] args) {
// 资源绑定器,只能绑定xx.Properties文件,并且这个文件必须在类路径下,文件扩展名也必须是Properties
// 并且在写路径的时候,路径后面的扩展名不能写
ResourceBundle bundle = ResourceBundle.getBundle("classinfo2");
String className = bundle.getString("className");
System.out.println(className);
}
}

浙公网安备 33010602011771号