注解和反射

注解和反射

注解(java.Annotation)

  • 注释:给人看的
  • 注解:给程序看也给人看

注解的作用

  • 不是程序本身,可以对程序做出解释
  • 可以被其他程序(例如:编译器等)读取
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yaswGJsQ-1642507130038)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20210507213155187.png)]

内置注解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2GtamK4W-1642507130039)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20210507213540822.png)]

元注解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7Vgflp09-1642507130039)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20210507213721231.png)]

  • 相当于一个约束,例如你创建了一个注解,他就用来约束你用在哪里,例如用在方法里或者类里

  • //定义一个注解
    //Target  表示我们的注解可以用在哪些地方,例如用在方法或类中
    @Target(value = {ElementType.METHOD,ElementType.TYPE})
    
    //Retention  表示我们的注解在什么地方还有效
    @Retention(value = RetentionPolicy.RUNTIME)
    
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1od1oNtI-1642507130040)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20210507214643801.png)]

自定义注解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BdeoFnRg-1642507130040)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20210507214815440.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HjSVgz85-1642507130040)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20210507215238850.png)]

反射(Java.Reflection)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yn2T15LR-1642507130041)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20210507215511556.png)]

  • 正常方式:引入需要的“包类”名称—通过new实例化—取得实例对象
  • 反射对象:实例对象—getClass()方法—得到完整的“包类”的名称

反射功能

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lNSQVwc1-1642507130041)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20210507220816869.png)]

  • 优点:可以实现动态创建对象和编译,体现出很大的灵活性
  • 缺点:对性能有影响,使用反射是一种解释操作,我们可以告诉jvm,我们希望做什么并且满足我们的要求,这类操作总是慢于 直接执行的操作。
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rV26E8ov-1642507130041)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20210511192759614.png)]

得到class类的几种方式

package lianxi;

public class Test01 {
    public static void main(String[] args) throws ClassNotFoundException {
        Person person = new Student();
        System.out.println("这个人是"+person.name);

        //通过对象获得
        Class c1=person.getClass();
        System.out.println(c1.hashCode());

        //通过forname获得
        Class c2=Class.forName("lianxi.Student");
        System.out.println(c2.hashCode());

        //通过类名.class获得
        Class c3=Student.class;
        System.out.println(c3.hashCode());
        
        //基本内置类型的包装类都有一个Type属性
        //得到的结果返回基本数据类型int
        Class c4 = Integer.TYPE;
        System.out.println(c4.hashCode());
        
        //获得父类类型
        Class c4=c1.getSuperclass();
        System.out.println(c5);
        

    }

}
class Person{
    String name;
    public Person(){

    }
    public Person(String name){
        this.name = name;
    }
    @Override
    public String toString(){
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }

}
class Student extends Person{
   public Student(){
       this.name="学生";
   }

}
class Teacher extends Person{
    public Teacher(){
        this.name="老师";
    }
}

哪些类型可以有class对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NPQWzWCi-1642507130042)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20210507222000794.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eoIk1WbA-1642507130042)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20210507222017707.png)]

  • 只要元素类型与纬度一样,就是同一个class

类的加载过程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gF9vPjfU-1642507130042)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20210509144743790.png)]

  1. 类的加载,类加载器运行
  2. 类的链接,将java类的二进制代码合并到JVM的运行状态之中(1.验证 2.准备 3.解析)
  3. 类的初始化,jvm执行,执行类构造器
  4. 程序初始化时会首先开始类的加载然后创建java.lang.Class对象,然后如果通过main方法new对象,才会生成一个在栈中承接new类的对象。和程序加载时生成的java.lang.Class一样,new出来的类会去找一开始加载生成的class文件
  5. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VbypMhCs-1642507130043)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20210509145838045.png)]

什么时候会发生类初始化[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EB3F5eig-1642507130043)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20210509150042684.png)]

类的主动引用(一定会发生类的初始化)
  1. 当虚拟机启动先初始化main方法所在的类
  2. new一个类的对象
  3. 使用反射
类的被动引用(不会发生类的初始化)
  1. 子类调用父类的静态方法变量不会不会加载子类
  2. 常量也就是使用final修饰的也不会引起父类跟子类的初始化
类加载器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OS4IJ4Oo-1642507130043)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20210509152908430.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iuGwvy4S-1642507130043)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20210509152945237.png)]

package lianxi;

public class Test03 {
    public static void main(String[] args) throws ClassNotFoundException {
        //获取系统类加载器
        ClassLoader systemClassLoader=ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);

        //获取系统类加载器的父类加载器--》扩展类加载器
        ClassLoader parent=systemClassLoader.getParent();
        System.out.println(parent);

        //获取扩展类加载器的父类加载器--》根加载器(c/c++)
        ClassLoader parent1=parent.getParent();
        System.out.println(parent1);

        //测试当前类是哪个加载器加载的
        ClassLoader classLoader=Class.forName("lianxi.Test03").getClassLoader();
        System.out.println(classLoader);

        //测试jdk内置的类是谁加载的
        classLoader = Class.forName("java.lang.Object").getClassLoader();
        System.out.println(classLoader);

        //如何获得系统类加载器可以加载的路劲

        System.out.println(System.getProperty("java.class.path"));

    }
}

获取运行时类的完整结构

  • 通过反射获取运行类时的完整结构
  • feild。method,constructor,superclass,interface,annotation
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2tUajLY7-1642507130044)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20210509160855184.png)]
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AdZuYfxd-1642507130044)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20210509160922735.png)]
  • 获取public属性用getFields(),找到全部的属性用getDeclaredFields();
  • 获取public方法用getMethods(),获取本类所有方法用getDeclaredMethods();

动态创建对象执行方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1PpCmg6k-1642507130044)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20210510232045585.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yhp1nzyT-1642507130044)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20210510232030087.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qmBsRCZM-1642507130045)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20210510232143543.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-or3bl1m1-1642507130045)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20210510232157569.png)]

package lianxi;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Test04 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        //获取class对象
        Class c1 = Class.forName("lianxi.User");

       /* //构造一个对象
        User user=(User) c1.newInstance();//本质是调用了类的无参构造
        System.out.println(user);*/

        //通过构造器构造对象,可以不用写无参构造
        Constructor constructor =c1.getDeclaredConstructor(String.class,int.class,int.class);
        User user1 = (User)constructor.newInstance("姚海",001,18);
        System.out.println(user1);
        
        
        //通过反射调用普通方法
        User user2=(User)c1.newInstance();
        //通过反射获取一个方法
        Method setName=c1.getDeclaredMethod("setName", String.class);
           //invoke : 激活的意思
        //invoke的使用,通过反射获取的方法然后传递对象,在输入方法的值---->>(对象,"方法的值")
        setName.invoke(user2,"孙烨辰");
        System.out.println(user2.getName());
        
        


    }
}

性能对比分析

package lianxi;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

//分析性能问题
public class Test05 {

    //普通方法调用
    public static void test01(){
        User user =new User();
        long startTime = System.currentTimeMillis();

        for (int i = 0; i < 100000000; i++) {
            user.getName();
        }

        long endTime = System.currentTimeMillis();
        System.out.println("普通方法执行10亿次"+(endTime-startTime)+"ms");
    }

    //反射方法调用
    public static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user =new User();
        Class c1=user.getClass();

        Method getName = c1.getDeclaredMethod("getName",null);
        long startTime = System.currentTimeMillis();

        for (int i = 0; i < 100000000; i++) {
                getName.invoke(user,null);
        }

        long endTime = System.currentTimeMillis();
        System.out.println("反射方法执行10亿次"+(endTime-startTime)+"ms");

    }
    public static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user =new User();
        Class c1=user.getClass();

        Method getName = c1.getDeclaredMethod("getName",null);
        getName.setAccessible(true);

        long startTime = System.currentTimeMillis();

        for (int i = 0; i < 100000000; i++) {
            getName.invoke(user,null);
        }

        long endTime = System.currentTimeMillis();
        System.out.println("关闭检测后反射方法执行10亿次"+(endTime-startTime)+"ms");

    }

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        test01();
        test02();
        test03();
    }
}

反射操作泛型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7tsazoBZ-1642507130045)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20210511001319254.png)]

package lianxi;

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

    }

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

        Type[] genericParameterTypes=method.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 = Test06.class.getMethod("test02",null);
        Type genericReturnType=method.getGenericReturnType();
        if(genericReturnType instanceof ParameterizedType){
            Type[] actualTypeArguments=((ParameterizedType)genericReturnType).getActualTypeArguments();
            for(Type actualTypeArgument:actualTypeArguments){
                System.out.println(actualTypeArgument);
            }

    }
}

获取注解信息

ORM

  • 了解什么是ORM?
    • Object relationship Mapping – 》对象关系映射
    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KzZOcYWS-1642507130046)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20210511175156202.png)]
  • java里面的类映射成数据库里的表
package lianxi;

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

//联系反射操作注解
public class Test07 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c1=Class.forName("lianxi.Student2");

        //通过反射获取注解
        Annotation[] annotations=c1.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);//结果为    @lianxi.Tableyao(value=db_student)
            
        }
        //获取注解的value的值
        Tableyao tableyao= (Tableyao) c1.getAnnotation(Tableyao.class);
        String value = tableyao.value();
        System.out.println(value);//    结果为db_student

        //获得类指定的注解信息
        Field f = c1.getDeclaredField("name");
        Fieldkuang annotation = f.getAnnotation(Fieldkuang.class);
        System.out.println(annotation.columnName());
        System.out.println(annotation.type());
        System.out.println(annotation.length());


    }

}
@Tableyao("db_student")
class Student2{
    @Fieldkuang(columnName = "db_id",type = "int",length = 10)
    private int id;
    @Fieldkuang(columnName = "db_age",type = "int",length = 10)
    private int age;
    @Fieldkuang(columnName = "db_name",type = "varchar",length = 3)
    private String name;


    public Student2() {

    }


    public Student2(int id, int age, String name) {
        this.id = id;
        this.age = age;
        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;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Student2{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

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

}

//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Fieldkuang{
    String columnName();
    String type();
    int length();
}
toString() {
        return "Student2{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

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

}

//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Fieldkuang{
    String columnName();
    String type();
    int length();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值