Java学习(十一) --------- 反射机制与注解


一、反射机制

1. 基本概念

反射的概念是由 Smith 在 1982 年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力, 并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。Java 中,反射是一种强大的工具。它使您能够创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码链接。反射允许我们在编写与执行时,使我们的程序代码能够接入装载到 JVM 中的类的内部信息,而不是源代码中选定的类协作的代码。这使反射成为构建灵活的应用的主要工具。但需注意的是:如果使用不当,反射的成本很高。

2. 作用

通过java语言中的反射机制可以操作字节码文件。程序运行时,java 系统会一直对所有对象进行所谓的运行时类型识别,这项信息记录了每个对象所属的类。通过专门的类可以访问这些信息。用来保存这些信息的类是class 类,class 类为编写可动态操纵的 java 代码程序提供了强大功能。

3. 构建Class对象

//方法一 : Class.forName();

try {
 // 构造 Class 对象的第一种方法
     Class clazz = Class.forName("java.lang.String");
     Object obj = clazz.newInstance();
     System.out.println(obj);
 } catch ( ClassNotFoundException e ) {
     e.printStackTrace();
 } catch (IllegalAccessException e) {
     e.printStackTrace();
 } catch ( InstantiationException e) {
     e.printStackTrace();
 }
//方法二 : 类.class
try {
 // 构造 Class 对象的第二种方法
     Class stringClass = String.class;
     System.out.println(stringClass);
 } catch ( ClassNotFoundException e ) {
     e.printStackTrace();
 } catch (IllegalAccessException e) {
     e.printStackTrace();
 } catch ( InstantiationException e) {
     e.printStackTrace();
 }
//方法三 : Object.getClass()

try {
    // 构造 Class 对象的第三种方法
    String s = "s";
    stringClass = s.getClass();
    System.out.println(stringClass);
 } catch ( ClassNotFoundException e ) {
    e.printStackTrace();
 } catch (IllegalAccessException e) {
    e.printStackTrace();
 } catch ( InstantiationException e) {
    e.printStackTrace();
 }

4. Java反射中主要类与方法

:反射机制的相关类在 java.lang.reflect.*;包下

java.lang.Class:代表整个字节码,代表一个类型,代表整个类.
java.lang.reflect.Method:代表字节码中的方法字节码。代表类中的方法.
java.lang.reflect.Constructor:代表字节码中的构造方法字节码.代表类中的构造方法
java.lang.reflect.Field:代表字节码中的属性字节码.代表类中的成员变量(静态变量+实例变量).

方法

1.getConstructors();//获取构造方法
2.getDeclaredMethods();//获取类中方法
3.getDeclaredFields();//获取类中属性
4.getName(); //获取方法/类/属性名称
5.getModifiers();//获取方法修饰符
6.getParameterTypes();//获取方法修饰符
7.getReturnType();//获取方法的返回值类型
8.getType();//获取变量类型
9.get();//获取变量的值
10.getInterfaces();//获取接口名称
11.getSuperclass();//获取类对象的父类
12.getPackage();//获取所在包名
13.newInstance();//获取类对象
14.setAccessible(true);//私有设置可以访问
15.set();//给对象中变量赋值
16.getMethod("方法名");//对象方法的反射调用;
17.invoke();//调用静态方法

5. 路径问题

String path / InputStream in = Thread.currentThread().getContextClassLoader().getResource("写相对路径,但是这个相对路径从src出发开始找").getPath();	//这种方式是为了获取一个文件的绝对路径

6. 快速绑定属性资源文件

ResourceBundle bundle = ResourceBundle.getBundle("路径");
String value = bundle.getString(key);
//要求:
//第一这个文件必须在类路径下
//第二这个文件必须是以.properties结尾

7. 反射与安全性

在处理反射时安全性是一个较复杂的问题。反射经常由框架型代码使用,由于这一点,我们可能希望框架能够全面介入代码,无需考虑常规的介入限制。但是,在其它情况下,不受控制的介入会带来严重的安全性风险,例如当代码在不值得信任的代码共享的环境中运行时。

8. 反射的缺点

性能问题。使用反射基本上是一种解释操作,我们可以告诉 JVM,我们希望做什么并且它满足我们的要求。用于字段和方法接入时反射要远慢于直接代码。性能问题的程度取决于程序中是如何使用反射的。如果它作为程序运行中相对很少涉及的部分,缓慢的性能将不会是一个问题。

使用反射会模糊程序内部实际要发生的事情。程序人员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术会带来维护问题。反射代码比相应的直接代码更复杂。解决这些问题的最佳方案是保守地使用反射——仅在它可以真正增加灵活性的地方——记录其在目标类中的使用。

9. 补充

只想让一个类的 “静态代码块” 执行 :

Class.forName(“该类的类名”);这样类就加载,类加载的时候,静态代码块执行。在这里,对该方法的返回值不感兴趣,主要是为了使用“类加载”这个动作。

二 、注解

1. 注解的概念

Annotation(注解)就是Java提供了一种元程序中的元素关联任何信息和着任何元数据(metadata)的途径和方法。Annotion(注解)是一个接口,程序可以通过反射来获取指定程序元素的Annotion对象,然后通过Annotion对象来获取注解里面的元数据。

2. 注解的作用

编写文档:通过代码里标识的元数据生成文档。
代码分析:通过代码里标识的元数据对代码进行分析。
编译检查:通过代码里标识的元数据让编译器能实现基本的编译检查。

3. 基本内置注释

@Override 注释能实现编译时检查,你可以为你的方法添加该注释,以声明方法是用于覆盖父类中的方法。如果该方法不是覆盖父类的方法,将会在编译时报错。例如我们为某类重写 toString() 方法却写成了 tostring() ,并且我们为该方法添加了@Override 注释,那么编译是无法通过的。

@Deprecated 的作用是对不应该在使用的方法添加注释,当编程人员使用这些方法时,将会在编译时显示提示信息,它与 javadoc 里的 @deprecated 标记有相同的功能。

@SuppressWarnings 与前两个注释有所不同,你需要添加一个参数才能正确使用,这些参数值都是已经定义好了的,我们选择性的使用就好了,参数如下:

  1. deprecation 使用了过时的类或方法时的警告
  2. unchecked 执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型
  3. fallthrough 当 Switch 程序块直接通往下一种情况而没有 Break 时的警告
  4. path 在类路径、源文件路径等中有不存在的路径时的警告
  5. serial 当在可序列化的类上缺少 serialVersionUID 定义时的警告
  6. finally 任何 finally 子句不能正常完成时的警告
  7. all 关于以上所有情况的警

4. 自定义注解类型

public @interface NewAnnotation {

}

public class AnnotationTest {
   @NewAnnotation
   public static void main(String[] args) {
   
   }
}

5. 注解的使用

class child extends Father {
	@Override  //表示子类重写了父类的方法
	public void test(){
	}
}

 @Deprecated  //被@Deprecated修饰的类、方法、变量等表示不建议使用的
 public String convertDate(String date) {
    return new Date(date).toString(); 
}

@SuppressWarnings("all")   //抑制所有类型的警告
public void addItems(String item){  
   List items = new ArrayList();  
   items.add(item);  
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

在森林中麋了鹿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值