反射机制:java语言通过此可以更改字节码文件(class文件),类似黑客
与之相关的类有java.class
java.lang.reflect.Field,类的属性,静态变量,实例变量
java.lang.reflect.Constructor代表构造方法字节码,类的构造方法
java.lang.reflect.Method代表方法字节码,类的静态,非静态方法
- 首先要获取class文件,通过class包获取,内部有一个Forname静态方法,内部参数是string类型,可以输入想要获取字节码的包
- Class s=Class.Forname(“java.utile.date”);
- 这里涉及到一个编译异常,用try catch解决(复习复习以前的异常处理)
- try catch来解决
- s==d,表达的是内存地址比较是否一样
- 上面是一种方法,
- 还有一种Class s=对象名.getClass();getclass()可以获取对象的class文件
- 都保存的是.class文件。这个文件再内存中之保存一份。如下图,两个保存的都是String.class字节码文件,
package reflect01;
import com.sun.istack.internal.localization.NullLocalizable;
public class R01 {
public static void main(String[] args) {
Class s= null;
try {
s=Class.forName("java.lang.String");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
String sd="dfsd";
Class f=sd.getClass();
System.out.println(s==f);
}
}
输出d的值是类的包名
输出结果为true、
下图为第三种方式
Class de=Date.class;
每种属性都有class字节码文件,下图int这样就不要了
字节码在jvm只保存一个
- 下面介绍一个方法newinstance,通过反射来实例化对象
package reflect01;
public class R021 {
//定义了一个R2的类以及无参构造防发
public static void main(String[] args) {
R02 e2=new R02();
System.out.println(e2);
try {
Class x=Class.forName("reflect01.R02");
Object object=x.newInstance();//调用类的无参构造方法,若没有无参构造方法会出错,
// 若有其它构造方法会覆盖掉无参,也会出错
System.out.println(object);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
使用两种调用无参构造方式,第二种虽然麻烦需要try/catch,但是可拓展比直接new灵活,使用了反射机制,也保证必须无参构造方法存在
- 下面实践它的灵活性
1,创建一个配置文件properties,//文本文件不用编译,用io流读的方式赋值给filereader类型文件,
2,创建一个proper对象,该对象调用方法load加载filereader对象。proper对象就有内容了
3,下面进行反射,Class类型接受,右方导入配置文件的名称。
4,调用无参构造方法,只要更改配置文件里面的内容就可多类型输出各种类型的构造方法
package reflect01;
import java.io.FileReader;
import java.util.Properties;
public class R021 {
//定义了一个R2的类以及无参构造防发
public static void main(String[] args) throws Exception {
FileReader fileReader = new FileReader("D:\\IDEA项目汇总斜杠分类\\heima1\\Reflect\\src\\reflect01\\classinfo.properties");
Properties properties = new Properties();
properties.load(fileReader);//加载存入
fileReader.close();//关
// Class c=Class.forName("ClassName");错误
//加载完成要读入名字
String classname = properties.getProperty("ClassName");//字符串类型;好啦,赋值成功
Class c = Class.forName(classname);//里面可以是string,也本身只能是string
Object object = c.newInstance();//TMD,必须加返回值啊,因为它饭会的是无参构造函数,Object 雷星来接受
System.out.println(object);
}
}
properties不用加分号
要注意加入路径名,不要只有类名。这是只要更改配置文件即可
- 未完,待更新,等我做完数据库实验