反射和注解
注解
内置注解
-
@Deprecated
// @Deprecated 意思是不推荐使用 @Deprecated public static void test(){ }
使用
@Deprecated
注解的方法在使用时会有这种提示。
-
@Override
// @Override 重写父类的方法 @Override public String toString() { return super.toString(); }
-
@SuppressWarnings
镇压警告@SuppressWarnings("all")
元注解( meta-annotation )
元注解的作用就是注解其他注解,Java 定义了 4 个标准的 meta-annotation 类型。
- @Target:描述注解的作用范围
- @Retention:表示需要在什么级别保存保存该注释信息,用于描述注解的生命周期。
(Source < Class < Runtime) - @Document:说明该注解将被包含在 javadoc 中
- @Inherited:说明该类的子类可以继承父类的注解
自定义注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
int id();
String name() default "klaus";
}
反射
一个类在内存中只有一个 Class 对象
一个类被加载后,类的整个结构都被封装在 class 中
package com.klaus.reflection;
// 什么是反射
public class Test extends Object{
public static void main(String[] args) throws ClassNotFoundException {
Class c1 = Class.forName("com.klaus.reflection.USer");
Class c2 = Class.forName("com.klaus.reflection.USer");
Class c3 = Class.forName("com.klaus.reflection.USer");
Class c4 = Class.forName("com.klaus.reflection.USer");
// 哈希值相同
System.out.println(c1.hashCode());
System.out.println(c2.hashCode());
System.out.println(c3.hashCode());
System.out.println(c4.hashCode());
}
}
class USer{
}
获取 class 的方法
package com.klaus.reflection;
public class Test2 {
public static void main(String[] args) throws ClassNotFoundException {
Person person = new Student();
System.out.println("这个人是" + person.name); //这个人是学生
//1. 通过对象获得
Class c1 = person.getClass();
System.out.println(c1.hashCode());//460141958
//2.forName
Class c2 = Class.forName("com.klaus.reflection.Student");
System.out.println(c2.hashCode());//460141958
//3.通过类名.class获得
Class c3 = Student.class;
System.out.println(c3.hashCode());//460141958
//4.基本内置类型有 Type方法
Class c4 = Integer.TYPE;
System.out.println(c4);//int
//5.获得class的父类型
Class c5 = c1.getSuperclass();
System.out.println(c5);//class com.klaus.reflection.Person
}
}
class Person{
String name;
public Person() {}
}
class Student extends Person{
public Student() {
this.name = "学生";
}
}
class Teacher extends Person{
public Teacher(){
this.name = "老师";
}
}
类的初始化
类的主动引用一定会发生类的初始化
- 虚拟机启动,先初始化 main 方法所在的类
- new 一个对象
- 使用类的静态成员(除了 final 常量)和静态方法
- 使用 java.lang.reflect 包的方法进行反射调用
- 初始化一个类,如果父类没有被初始化,那么先初始化父类
被动引用
- 访问一个静态域时,只有真正声明它的类才会被初始化
- 通过数组定义类引用,不会触发此类的初始化(比如说定义了一个对象类型的数组)
- 引用常量不会触发类的初始化(常量在链接阶段就存入常量池了)
反射的使用
Class c1 = Class.forName("com.klaus.reflection.User");
无参构造动态创建对象
// 无参构造
User user = (User) c1.newInstance();
System.out.println(user); / /USer{name='null', id=0, age=0}
有参构造创建对象
// 有参构造
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
User instance =(User) constructor.newInstance("klaus", 12, 2);
System.out.println(instance);// USer{name='klaus', id=12, age=2}
通过反射调用方法
//通过反射调用方法
Method setName = c1.getDeclaredMethod("setName", String.class);// 获得方法
setName.invoke(instance,"Klaus08");
System.out.println(instance);//USer{name='Klaus08', id=12, age=2}
通过反射操作属性
//通过反射操作属性,对于私有属性要关闭 “安全检测”
User user2 =(User) c1.newInstance();
Field name = c1.getDeclaredField("name");
name.setAccessible(true);
name.set(user2,"zoe");
System.out.println(user2.getName()); //zoe
全部代码如下:
package com.klaus.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
// 动态创建对象
public class Test7 {
public static void main(String[] args) throws Exception {
Class c1 = Class.forName("com.klaus.reflection.User");
// 无参构造
User u = (User) c1.newInstance();
System.out.println(u);
// 有参构造
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
User instance =(User) constructor.newInstance("klaus", 12, 2);
System.out.println(instance);
//通过反射调用方法
Method setName = c1.getDeclaredMethod("setName", String.class);// 获得方法
setName.invoke(instance,"Klaus08");
System.out.println(instance);
//通过反射操作属性,对于私有属性要关闭 “安全检测”
User user2 =(User) c1.newInstance();
Field name = c1.getDeclaredField("name");
name.setAccessible(true);
name.set(user2,"zoe");
System.out.println(user2.getName());
}
}
setAccessible
反射&注解
通过反射获得注解信息,下面的代码演示了一般 ORM 注解的原理,通过注解获得属性对应列名,使 pojo 和表联系起来。
package com.klaus.reflection;
import java.lang.annotation.*;
import java.lang.reflect.Field;
public class Test8 {
public static void main(String[] args) throws Exception {
Class c1 = Class.forName("com.klaus.reflection.Student_");
//通过反射获得注解
Annotation[] annotation = c1.getAnnotations();
for (Annotation annotation1 : annotation) {
System.out.println(annotation1);//@com.klaus.reflection.TableKlaus(value=stu)
}
TableKlaus tableKlaus = (TableKlaus)c1.getAnnotation(TableKlaus.class);
String value = tableKlaus.value();
System.out.println(value);//stu
Field name = c1.getDeclaredField("name");
ColumnKlaus columnKlaus = name.getAnnotation(ColumnKlaus.class);
System.out.println(columnKlaus.column());//name
System.out.println(columnKlaus.type());//type
}
}
@TableKlaus("stu")
class Student_{
@ColumnKlaus(column ="name",type = "String")
String name;
@ColumnKlaus(column = "id", type = "int")
int id;
}
// 类的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableKlaus{
String value();
}
// 属性注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface ColumnKlaus{
String column();
String type();
}
本文来自博客园,作者:klaus08,转载请注明原文链接:https://www.cnblogs.com/klaus08/p/15121206.html