练习泛型擦除(掌握概念,了解代码)
集合中的泛型只在java文件中存在,当编译成class文件之后,就没有泛型了。
package com.itheima.reflectdemo;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class ReflectDemo8 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//1.创建集合对象
ArrayList<Integer> list = new ArrayList<>();
list.add(123);
// list.add("aaa");
//2.利用反射运行add方法去添加字符串
//因为反射使用的是class字节码文件
//获取class对象
Class clazz = list.getClass();
//获取add方法对象
Method method = clazz.getMethod("add", Object.class);
//运行方法
method.invoke(list,"aaa");
//打印集合
System.out.println(list);
}
}
修改字符串的内容(掌握概念,了解代码)
在这个练习中,我需要你掌握的是字符串不能修改的真正原因。
字符串,在底层是一个byte类型的字节数组,名字叫做value
private final byte[] value;
真正不能被修改的原因:final和private
final修饰value表示value记录的地址值不能修改。
private修饰value而且没有对外提供getvalue和setvalue的方法。所以,在外界不能获取或修改value记录的地址值。
如果要强行修改可以用反射:
String s = "abc";
String ss = "abc";
// private final byte[] value= {97,98,99};
// 没有对外提供getvalue和setvalue的方法,不能修改value记录的地址值
// 如果我们利用反射获取了value的地址值。
// 也是可以修改的,final修饰的value
// 真正不可变的value数组的地址值,里面的内容利用反射还是可以修改的,比较危险
//1.获取class对象
Class clazz = s.getClass();
//2.获取value成员变量(private)
Field field = clazz.getDeclaredField("value");
//但是这种操作非常危险
//JDK高版本已经屏蔽了这种操作,低版本还是可以的
//临时修改权限
field.setAccessible(true);
//3.获取value记录的地址值
byte[] bytes = (byte[]) field.get(s);
bytes[0] = 100;
System.out.println(s);//dbc
System.out.println(ss);//dbc
练习,反射和配置文件结合动态获取的练习
需求: 利用反射根据文件中的不同类名和方法名,创建不同的对象并调用方法。
分析:
①通过Properties加载配置文件
②得到类名和方法名
③通过类名反射得到Class对象
④通过Class对象创建一个对象
⑤通过Class对象得到方法
⑥调用方法
public class ReflectDemo9 {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//1.读取配置文件的信息
Properties prop = new Properties();
FileInputStream fis = new FileInputStream("day14-code\\prop.properties");
prop.load(fis);
fis.close();
System.out.println(prop);
String classname = prop.get("classname") + "";
String methodname = prop.get("methodname") + "";
//2.获取字节码文件对象
Class clazz = Class.forName(classname);
//3.要先创建这个类的对象
Constructor con = clazz.getDeclaredConstructor();
con.setAccessible(true);
Object o = con.newInstance();
System.out.println(o);
//4.获取方法的对象
Method method = clazz.getDeclaredMethod(methodname);
method.setAccessible(true);
//5.运行方法
method.invoke(o);
}
}
配置文件中的信息:
classname=com.itheima.a02reflectdemo1.Student
methodname=sleep
java properties文件读写
读
Properties prop = new Properties();
FileInputStream fis = new FileInputStream("day14-code\\prop.properties");
prop.load(fis);
fis.close();
写
OutputStream fos = new FileOutputStream("shortcut.properties");
prop.setProperty("ip", ip.trim());
prop.setProperty("port", port.trim());
prop.store(fos,"this is header");
fos.close();
利用发射保存对象中的信息
public class MyReflectDemo {
public static void main(String[] args) throws IllegalAccessException, IOException {
/*
对于任意一个对象,都可以把对象所有的字段名和值,保存到文件中去
*/
Student s = new Student("小A",23,'女',167.5,"睡觉");
Teacher t = new Teacher("播妞",10000);
saveObject(s);
}
//把对象里面所有的成员变量名和值保存到本地文件中
public static void saveObject(Object obj) throws IllegalAccessException, IOException {
//1.获取字节码文件的对象
Class clazz = obj.getClass();
//2. 创建IO流
BufferedWriter bw = new BufferedWriter(new FileWriter("myreflect\\a.txt"));
//3. 获取所有的成员变量
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
//获取成员变量的名字
String name = field.getName();
//获取成员变量的值
Object value = field.get(obj);
//写出数据
bw.write(name + "=" + value);
bw.newLine();
}
bw.close();
}
}