反射与注解学习笔记
反射和注解
代码:https://gitee.com/longzhiquan/reflection
注解 Annotation
1. 内置注解
- @Override: 重写超类中的另一个方法
- @Deprecated: 不鼓励程序员用的方法
- @SuppressWarnings: 抑制编译时的警告信息
- @SuppressWarnings("all")
- @SuppressWarnings("unchecked")
2. 元注解
解释其他注解的注解
- @Target: 描述注解的适用范围
- @Retention: 描述注解的生命周期
- @Document: 说明注解被包含在javadoc中
- @Inherited: 说明子类可以继承父类中的该注解
import java.lang.annotation.*;
//测试元注解
public class Test01 {
public void test(){
}
}
//在方法上有效,在类上有效
@Target(value = {ElementType.METHOD, ElementType.TYPE})
//在运行时有效
//runtime>class>source
@Retention(value = RetentionPolicy.RUNTIME)
//将注解生成在javadoc中
@Documented
//子类可以继承父类注解
@Inherited
@interface MyAnnotation{
}
3. 自定义注解
import java.lang.annotation.*;
public class Test02 {
//如果没有默认值,我们就必须给注解赋值
@MyAnnotation2(name="hou", schoolds = {"大学"})
public void test(){
}
//如果只有一个参数用value命名,可以省略value
@MyAnnotation3("hou")
public void test1(){
}
}
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
//注解参数:参数类型+参数名()默认值是空
String name() default "";
int age() default 0;
int id() default -1; //如果默认值是-1,代表不存在
String[] schoolds();
}
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation3{
String value();
}
反射 reflection
1. 概述
反射机制允许程序在执行期间借助于Rflection API取得任何类的内部消息,并能直接操纵任意对象的内部属性及方法。
Class c = Class.forName("java.lang.String")
加载完类之后,在堆内存的方法区中就产生一个Class类型的对象
正常方式:
- 引入需要的包
- 通过new实例化
- 去的实例化对象
反射方式:
- 实例化对象
- getClass()方法
- 得到完成的”包类“名称
2. 反射对象
package hou;
public class Test03 {
public static void main(String[] args) throws ClassNotFoundException {
//通过反射获得class对象
Class c1 = Class.forName("hou.User");
System.out.println(c1);
//hashcode一样
Class c2 = Class.forName("hou.User");
Class c3 = Class.forName("hou.User");
Class c4 = Class.forName("hou.User");
}
}
class User{
private String name;
private int age;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
三种方法:
package hou;
public class Test04 {
public static void main(String[] args) throws ClassNotFoundException {
People people = new Student();
System.out.println(people);
//通过对象获得
Class c1 = people.getClass();
//forname获得
Class c2 = Class.forName("hou.People");
//通过类名.class获得
Class<Student> c3 = Student.class;
//hashcode一样
//获得父类
Class c5 = c1.getSuperclass();
System.out.println(c5);
}
}
class People{
private String name;
public People() {
}
public People(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
'}';
}
}
class Student extends People{
public Student() {
super("学生");
}
}
class Teacher extends People{
public Teacher() {
super("Teacher");
}
}
所有类型对象
public class Test05 {
public static void main(String[] args) {
Class c1 = Object.class;
Class c2 = Comparable.class;
Class c3 = String[].class;
Class c4 = int[][].class;
Class c5 = Override.class; //注解
Class c6 = ElementType.class; //枚举
Class c7 = Integer.class; //基本数据类型
Class c8 = void.class; //void
Class c9 = Class.class; //Class
}
}
3. 类加载理解
public class Test06 {
public static void main(String[] args) {
A a = new A();
System.out.println(A.m);
}
}
class A{
static{
System.out.println("A静态代码块");
m = 300;
}
static int m = 200;
public A(){
System.out.println("A无参");
}
}
output
A静态代码块
A无参
200
4. 类的初始化
package hou;
public class Test07 {
static {
System.out.println("Main");
}
public static void main(String[] args) throws ClassNotFoundException {
//主动引用
// Son son = new Son();
//反射也会产生主动引用
// Class.forName("hou.Son");
// Main
// father
// Son
//不会产生引用
// System.out.println(Son.f);
// Main
// father
// 0
// Son[] sons = new Son[5];
// Main
System.out.println(Son.n);
// Main
// 1
}
}
class Father{
static int f = 0;
static {
System.out.println("father");
}
}
class Son extends Father{
static{
System.out.println("Son");
m = 300;
}
static int m = 200;
static final int n = 1;
}
5. 类的加载器
public class Test08 {
public static void main(String[] args) throws ClassNotFoundException {
//获取系统类加载器
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
System.out.println(classLoader);
//获取系统加载器的父类-->扩展加载器
ClassLoader classLoader1 = classLoader.getParent();
System.out.println(classLoader1);
//获取扩展加载器的父类-->根加载器
ClassLoader classLoader2 = classLoader1.getParent();
System.out.println(classLoader2);
//系统类加载器
System.out.println(Class.forName("hou.Test08").getClassLoader());
//根加载器
System.out.println(Class.forName("java.lang.Object").getClassLoader());
}
}
6. 获取运行时的结构
package hou;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test09 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class c1 = Class.forName("hou.User");
System.out.println(c1.getName()); //包名+类名
System.out.println(c1.getSimpleName()); //类名
//获得所有属性
Field[] fields = c1.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
//获得public方法
Method[] methods = c1.getMethods();
for (Method method : methods) {
System.out.println(method);
}
//获得指令属性
Field name = c1.getDeclaredField("name");
System.out.println(name);
//获得指定方法
Method getname = c1.getMethod("getName", null);
Method setname = c1.getMethod("setName", String.class);
System.out.println(getname);
System.out.println(setname);
//获得指定的构造器
Constructor[] constructors = c1.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
//获得指令构造器
Constructor constructor = c1.getConstructor(String.class, int.class);
System.out.println(constructor);
}
}
7. 动态创建对象
package hou;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test10 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
Class c1 = Class.forName("hou.User");
User use = (User) c1.newInstance();
System.out.println(use);
Constructor constructor = c1.getConstructor(String.class, int.class);
User user2 = (User) constructor.newInstance("hou", 18);
System.out.println(user2);
//通过反射调用方法
User user3 = (User) c1.newInstance();
Method setname = c1.getMethod("setName", String.class);
setname.invoke(user3, "dong");
System.out.println(user3.getName());
//获取反射操作属性
User user4 = (User) c1.newInstance();
Field field = c1.getDeclaredField("age");
field.setAccessible(true);
field.set(user4, 100);
System.out.println(user4.getAge());
}
}
8. 反射操作泛型
通过反射获取泛型
package hou;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
public class Test11 {
public void test1(Map<String, User> map){
System.out.println("test1");
}
public List<User> test2(){
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
Method method1 = Test11.class.getMethod("test1", Map.class);
Type[] genericParameterTypes = method1.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
System.out.println(genericParameterType);
if(genericParameterType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
Method method2 = Test11.class.getMethod("test2", null);
Type genericReturnType = method2.getGenericReturnType();
if(genericReturnType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
}
9. 反射操作注解
package hou;
import java.lang.annotation.*;
import java.lang.reflect.Field;
//反射操作注解
public class Test12 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("hou.Student2");
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
//获得注解的值
Table annotation = (Table) c1.getAnnotation(Table.class);
String value = annotation.value();
System.out.println(value);
Field name = c1.getDeclaredField("name");
MyField mf = name.getAnnotation(MyField.class);
System.out.println(mf.columnName());
System.out.println(mf.length());
System.out.println(mf.type());
}
}
@Table("hou")
class Student2{
@MyField(columnName = "dbname", type = "String", length = 10)
private String name;
@MyField(columnName = "dbid", type = "int", length = 2)
private int id;
@MyField(columnName = "dbage", type = "int", length = 2)
private int age;
public Student2() {
}
public Student2(String name, int id, int age) {
this.name = name;
this.id = id;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student2{" +
"name='" + name + '\'' +
", id=" + id +
", age=" + age +
'}';
}
}
//类名注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Table{
String value();
}
//属性注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyField{
String columnName();
String type();
int length();
}