注解
概述和理解
注解的开发已经是时代所趋向,未来的框架都是基于 注解 + 反射 + 设计模式
JDK中的元注解
元注解:对现有的注解进行解释说明以及限制(修饰注解的注解)
JDK5.0提供了4个标准的元注解类型,分别是:
- Retention:指明注解整体适用范围(默认是CLASS,反射时使用RUNTIME)
- Target:指明注解能修饰哪些层面,例如类、方法、构造器(指明注解能修饰哪些层面,例如类、方法、构造器…)
- Document:指明该注解编译后需不需要进入jdk文档
- Inherited:注解能被继承
使用
注解能做什么呢?
生成文档相关的注释
在编译时进行格式检查
跟踪代码的依赖,实现替代配置文件的功能
类似这样的注解,省略了配置文件的复杂性
自定义注解
- 用@interface声明注解
- 内部定义成员,通常使用value表示
- 用default定义成员的默认值
- 若没有定义成员,表明是一个标识作用
实现流程:
1、IDEA中,新建class文件
2、写入代码
①、不写value,类似重写方法override
②、写value,加默认值
3、其他地方使用
反射
概述和理解
反射相当于镜面,透过镜子看到类的结构, 通过反射可以对已有的实体对象进行解析
反射最重要的用途就是开发各种通用框架:
很多框架(比如 Spring)都是配置化的(比如Spring 通过 XML 配置模式装载 Bean),为了保证框架的通用性,他们可能根据配置文件加载不同的对象或类,调用不同的方法,这个时候就必须用到反射——运行时动态加载需要加载的对象。
优缺点
优点
使用反射机制,代码可以在运行时装配,提高了程序的灵活性和扩展性,降低耦合性,提高自适应能力。它允许程序创建和控制任何类的对象,无需硬编码目标类
缺点
-
性能问题:使用反射基本上是一种解释操作,JVM无法对这些代码进行优化,因此,反射操作的效率要比那些非反射操作低得多。反射机制主要应用在对灵活性和扩展性要求很高的系统框架上,对性能要求高的程序中不建议使用 -
安全限制:使用反射技术要求程序必须在一个没有安全限制的环境中运行 -
内部暴露:由于反射允许代码执行一些在正常情况下不被允许的操作(比如访问私有的属性和方法),所以使用反射可能会导致意料之外的副作用——代码有功能上的错误,降低可移植性。反射代码破坏了抽象性,因此当平台发生改变的时候,代码的行为就有可能也随着变化
疑问点
-
开发中既有反射也有new的方式建造对象,到底用哪个? 平常使用new,如果是动态的话用反射(比如前后台的交互,你不确定调用哪个方法,这时候可以用反射来动态代理) -
反射能调用私有,封装性隐藏私有,两者是否矛盾? 不矛盾,因为封装是建议,而反射要看用在什么地方。两者都不禁止私有的运用
哪些结构有反射
反射与动态代理
获取class实例的几个方式
public static void test3() throws Exception {
Class clazz1 = Person.class;
System.out.println(clazz1);
Person p1 = new Person();
Class clazz2 = p1.getClass();
System.out.println(clazz2);
Class clazz3 = Class.forName("com.company.Person");
System.out.println(clazz3);
ClassLoader classLoader = Main.class.getClassLoader();
Class clazz4 = classLoader.loadClass("com.company.Person");
System.out.println(clazz4);
}
public static void test4() throws Exception {
Properties pros = new Properties();
FileInputStream fis = new FileInputStream("src\\jdbc.properties");
pros.load(fis);
ClassLoader classLoader = Main.class.getClassLoader();
InputStream is = classLoader.getResourceAsStream("jdbc.properties");
pros.load(is);
String username = pros.getProperty("username");
String password = pros.getProperty("password");
System.out.println("姓名:"+username+",密码:"+password);
}
调用指定的属性、方法
public static void testShuxing() throws Exception {
Class<Person> personClass = Person.class;
Person p = personClass.newInstance();
Field name = personClass.getDeclaredField("name");
name.setAccessible(true);
name.set(p,"TOM");
System.out.println(name.get(p));
}
public static void testMethod() throws Exception {
Class<Person> personClass = Person.class;
Person p = personClass.newInstance();
Method showNation = personClass.getDeclaredMethod("showNation", String.class);
showNation.setAccessible(true);
Object china = showNation.invoke(p, "CHINA");
System.out.println(china);
}
|