反射与注解
注解
1 注解是什么?
注解,顾明思意,就是注释解释,其功能跟注释是一样的,注释是帮助人理解事务,而注解就是帮助计算机理解事务,即解释说明程序,方便计算机进行操作的。他是在jdk1.5以后才出现的。
2 注解有什么作用?
- 方便人员编写文档,在代码中标志的注解可以生成java的文档,就类似于java的api一样,我们可以自己来定义自己的api文档。
- 编译检查,在某些代码上面标志注解可以帮助实现编译期间的检查。比如子类继承父类,重写父类的某些方法,在被重写的方法前面有一个@override的注解。
3 jdk中常见的被定义的注解
@override :检查该注解标注的方法是否是继承父类的。
@deprecated:该注解标注的内容已过时,在idea中飘红的那些类或者方法。Deprecated英文含义-已弃用
@suppressWarnings:压制警告。suppressWarnings英文含义-取消警告
suppressWarnings在用的时候一般需要传入参数,正常的来说,传入all,即
@SuppressWarnings(“all”)–代表压制所有的警告。
4 自定义注解
我们不仅可以使用定义好的,还可以自己来定义注解。参考jdk定义好的注解,我们知道了自定义注解的格式要求,格式:元注解 +Public @interface 注解名称{ }。
本质:注解本质上是一个接口。所以接口中能定义的,注解中就能定义。
注解中的属性:即接口中定义的方法。
5 元注解
定义:用于描述注解的注解。有@target,@ Retention,@documentd,@inherited四个元注解。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qbR9k56g-1574906219167)(D:\文件笔记\images\元注解.png)]
反射
1 java文件是如何在计算机中运行的?
首先,java文件被保存在磁盘上;再通过javac进行编译成.class文件(字节码文件)。
再次,利用jvm的类加载器(classloader)把字节码文件加载进入内存,在内存中的。class文件被Class类来表示。
在Class类中,将类的属性封装为field对象
将类的构造方法封装为constructor对象
将类的普通方法封装为method对象。这就是反射机制。
反射:将类的各个组成部分->封装为其他对象。
2 获取Class字节码
三种方式:
① Class.forName(类的路径),将字节码文件加载进入内存,返回class对象,大多用于配置文件中
② 类名.class:通过类名的属性获取
③ 对象.getclass:获取类对象。
3 类对象的功能
类对象获取属性,构造方法,普通方法,类名
4 类对象获取属性
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cJnPCrmJ-1574906219169)(file:///C:\Users\刘平远\AppData\Local\Temp\msohtmlclip1\01\clip_image002.jpg)]类对象中的方法
Getfields()获取类中的public修饰的属性名称。返回的是一个field数组。
Getfeild(name)获取类中名为name的public属性对象,返回的是一个field对象。所获取的对象是类对象,如果要进行操作,需要将实例化对象传入。可以通过get/set方法来进行对对象的修改。
Getdeclarfields()获取所有的成员变量。不论什么类型,返回的是一个数组。
Getdeclarfields(name)获取指定名称为name的成员变量。方法类似于getfeild(name)。
5 类对象获取构造方法
能获取的构造方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jhmsFRpC-1574906219171)(D:\文件笔记\images\类对象获取构造方法.jpg)]
Class pc = Person.class;
//获取类对象的构造器,含有2个参数的
Constructor constructor = pc.getConstructor(String.class, int.class);
System.***out\***.println(constructor);
//利用构造器生成一个对象,就相当与 person p=new person(1,22)
Object o1= constructor.newInstance("1",22);
System.***out\***.println(o1);
//构造空参的构造函数
Constructor noagcon = pc.getConstructor();
Object o = noagcon.newInstance();
System.***out\***.println(o);
//如果创建的是空构造参数,可以简化,直接调用类对象的newinstance方法即可
//就等价与上面的那个。
Object o2 = pc.newInstance();
System.out.println(o2);
6 类对象获取成员方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fLapzW2K-1574906219172)(D:\文件笔记\images\类对象.jpg)]
获取成员方法
Class pc = Person.class;
//获取public声明的成员方法
Method[] publicmethods = pc.getMethods();
for (Method publicmethod : publicmethods) {
System.out.println(publicmethod);
}
//获取指定名称的public修饰方法
Method getagemethod = pc.getMethod("getAge");
//方法获取了,可以获取实例化对象的值。
System.out.println(getagemethod);
Person p=new Person();
//将实例化对象传入类方法中
System.out.println(getagemethod.invoke(p));
System.out.println("--------------------------------");
//获取所有的方法 (包括父类object类中的方法)
Method[] allmethods = pc.getDeclaredMethods();
for (Method allmethod : allmethods) {
System.out.println(allmethod);
//获取每个方法的名称
System.out.println(allmethod.getName());
}
7 反射与配置文件结合的实例
//加载配置文件
Properties pro=new Properties();
//获取class下的胚子文件的目录
InputStream resourceAsStream = Test2.class.getClassLoader().getResourceAsStream("pro.properties");
//加载到胚子文件
pro.load(resourceAsStream);
//获取类与方法名称
String className = pro.getProperty("className");
String Mname = pro.getProperty("methodName");
//反射的运用
//使用类加载器吧类加载到内存中
Class cls = Class.forName(className);
//实例话对象
Constructor constructor = cls.getConstructor();
//构造对象
Object o = constructor.newInstance();
//获取方法
Method method = cls.getMethod(Mname);
//运行方法。将需要运行方法的对象传入进去
method.invoke(o);
nstructor = cls.getConstructor();
//构造对象
Object o = constructor.newInstance();
//获取方法
Method method = cls.getMethod(Mname);
//运行方法。将需要运行方法的对象传入进去
method.invoke(o);