Day17-注解与反射

注解与反射

注解

可被其他程序(如:编译器)读取,可以对程序做出解释

以@注释名在代码中存在

内置注解

@Override

必须重写父类存在的方法,否则报错

@Deprecated

表示不鼓励使用该类或者方法或者属性

@SuppressWarnings(“xxx”)

抑制编译时的警告信息

元注解

用于注解其他注解的注解

@Target(value={})

约束其他注解可以使用的地方

@Retention

表示注解在什么地方还有效,一般写runtime

runtime>class>sources

@Documented

表示是否将注解生成在Javadoc中

@inherited

子类可以继承父类的注解

自定义注解

通过@interface 注解名{}来定义注解

参数类型+参数名+()来定义参数

  @Target({ElementType.METHOD,ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @interface MyInterface{
        String name() default "";       //如果不设置默认值,则必须填写
        int age();
    }

    @Target({ElementType.METHOD,ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @interface MyInterface1{
        String value();         //当只有一个参数,且参数名为value时,可以省略参数名
    }

    @MyInterface(age = 18)
    public static void test1(){}

    @MyInterface1("")
    public static void test2(){}

反射

Java被视为动态语言的关键,反射机制允许程序在执行期间借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性和方法

优点

可以实现动态创建对象和编译,体现很大的灵活性

缺点

影响性能

Class类

只能由系统创建,反射可以获取class类的对象, 在jvm中有且只有一个实例

package Reflection;

public class Test01 {
    public static void main(String[] args) throws ClassNotFoundException {
        Person person = new Student();

        //Class类的创建方法

        //方式一:通过对象获得
        Class c1 = person.getClass();
        //方式二:通过完整的类名获得
        Class c2 = Class.forName("Reflection.Student");
        //方式三:通过类名.class获得
        Class c3 = Student.class;

        //基本内置类都会有一个type属性
        Class c4 = Integer.TYPE;

        System.out.println(c1.hashCode());
        System.out.println(c2.hashCode());
        System.out.println(c3.hashCode());
        System.out.println(c4.hashCode());
    }
}
class Person{
    public String name;
    public int age;

    public Person() {
    }
}
class Student extends Person{
    public Student() {
        this.name = "学生";
    }
}
class Teacher extends Person{
    public Teacher(){
        this.name = "老师";
    }
}
通过反射获取类的信息
package Reflection;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

//获取类的信息
public class Test02 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        User user = new User();
        Class c1 = user.getClass();

        //获得类的名字
        System.out.println(c1.getName());       //获得类名+包名
        System.out.println(c1.getSimpleName()); //获得类名

        //获得类的属性
        Field[] fields = c1.getFields();        //获取方法中的公共属性
        fields =c1.getDeclaredFields();         //获取方法中的所有属性
        for(Field field:fields){
            System.out.println(field);
        }

        //获得类的方法
        Method[] method = c1.getMethods();      //获得子类和父类的所有方法
        method = c1.getDeclaredMethods();       //获得本类的所有方法
        for(Method method1:method){
            System.out.println(method1);
        }

        System.out.println("**********************");
        Method method1 = c1.getMethod("getName",null);      //获取指定的方法
        System.out.println(method1);
        
        //获取构造器,方法同上。。。
    }
}

通过反射动态创建对象
package Reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

//通过反射动态地创建对象
public class Test03 {
    public static void main(String[] args) throws Exception {
        Class c1 = Class.forName("Reflection.User");

        //方式一
        Object o = c1.newInstance();            //该类必须有无参构造器
        //方式二
        Constructor constructor = c1.getConstructor(String.class,int.class,int.class);
        User user = (User)constructor.newInstance("chenchenchen",18,1);
        System.out.println(user);

        //调用对象中的方法
        Method setName = c1.getMethod("setName", String.class);
        setName.invoke(user,"陈琛琛");
        System.out.println(user.getName());

        //调用对象中的属性
        Field name = c1.getDeclaredField("name");
        name.setAccessible(true);           //设置是否开启权限
        name.set(user,"haha");
        System.out.println(user.getName());
    }
}

性能对比

package Reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

//通过反射动态地创建对象
public class Test03 {
    public static void main(String[] args) throws Exception {
        Class c1 = Class.forName("Reflection.User");

        //方式一
        Object o = c1.newInstance();            //该类必须有无参构造器
        //方式二
        Constructor constructor = c1.getConstructor(String.class,int.class,int.class);
        User user = (User)constructor.newInstance("chenchenchen",18,1);
        System.out.println(user);

        //调用对象中的方法
        Method setName = c1.getMethod("setName", String.class);
        setName.invoke(user,"陈琛琛");
        System.out.println(user.getName());

        //调用对象中的属性
        Field name = c1.getDeclaredField("name");
        name.setAccessible(true);           //设置是否开启权限
        name.set(user,"haha");
        System.out.println(user.getName());
    }
}

泛型类型

package Reflection;

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 Test05 {
    public static void test1(Map<String,User> map, List<String> list){
        System.out.println("test1");
    }
    public Map<String,User> test2(){
        System.out.println("test2");
        return null;
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = Test05.class.getMethod("test1", Map.class, List.class);

        Type[] genericParameterTypes = method.getGenericParameterTypes();       //获得泛型的参数类型数组
        for (Type genericParameterType : genericParameterTypes) {               //打印类型
            if(genericParameterType instanceof ParameterizedType){              //如果是参数化类型,将其进行强制转换,然后调用方法获取真实参数类型
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {           //打印真实类型
                    System.out.println(actualTypeArgument);
                }
            }
        }

        method = Test05.class.getMethod("test2");
        Type genericReturnType = method.getGenericReturnType();
            if(genericReturnType instanceof ParameterizedType){
                Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println(actualTypeArgument);
                }
            }

    }
}

ORM

package Reflection;

import java.lang.annotation.*;
import java.lang.reflect.Field;

public class ORM {
    public static void main(String[] args) throws NoSuchFieldException {
        Final f = new Final();
        Class c1 = f.getClass();
        Annotation annotation = c1.getAnnotation(Table.class);
        System.out.println(annotation);
        //获取注解中的数据
        Table table = (Table)annotation;
        System.out.println(table.value());

        Field name = c1.getDeclaredField("id");     //属性的注解需要先获取到属性值
        name.setAccessible(true);
        TableTest annotation1 = name.getAnnotation(TableTest.class);
        System.out.println(annotation1.tableName());
        System.out.println(annotation1.type());
        System.out.println(annotation1.length());
    }
}

@Table("db_Test")
class Final{
    @TableTest(tableName = "Test",type = "String",length = 10)
    private String name;
    @TableTest(tableName = "Test",type = "int",length = 2)
    private int age;
    @TableTest(tableName = "Test",type = "int",length = 10)
    private int id;

    public Final() {
    }

    public Final(String name, int age, int id) {
        this.name = name;
        this.age = age;
        this.id = id;
    }

    @Override
    public String toString() {
        return "Final{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", id=" + id +
                '}';
    }
}

//类名注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Table{
    String value();     //表名
}

//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface TableTest{
    String tableName();
    String type();
    int length();
}

上一篇:Day17


下一篇:Day17 常用Api