Day6学习日记

注解Annotation

什么是注解

  • 作用
    • 对程序做出解释
    • 可以被其他程序(比如编译器)读取
  • 格式
    • 注解是以"@注释名"在代码中存在的,还可以添加一些参数值
    • 例如:@SuppressWarnings(value=“unchecked”)
  • 在哪里使用
    • 附加在package,class,method,field等上面,可以通过反射机制编程实现对这些元数据的访问

内置注解

  • @override:重写
  • @SuppressWarinings(“”):镇压警告 all 所有,unchecked 未检查 或者加多个值
  • @Deprecated:不推荐程序员使用,但可以使用
  • @FunctionaInterface:指定接口必须式函数式接口
  • @SafeVarargs:一直“堆污染警告”

元注解meta-annotation

  • @Target:注解作用范围

    public class ZiDingYi {
        @MyAnnotation
        public void test(){
        }
    }
    @Target(value={ElementType.METHOD,ElementType.ANNOTATION_TYPE})
    @interface MyAnnotation{
    }
    
    @MyAnnotation
    @interface My{
        
    }
    
  • @Retention:SOURCE<CLASS<RUNTIME

  • @Documented:包含在javadoc中

  • @Inherited:子类可以继承父类中的注解

自定义注解

  • @interface用来声明一个注解,格式:public @interface 注解名{}

  • 其中的每一个方法实际上式声明了一个配置参数,例如ElementType[] value()

  • 方法的名称就是参数的名称

  • 返回值类型就是参数的类型,只能基本类型,Class,String,enum(枚举)

  • 如果只有一个参数成员,一般参数名为value

  • 注解元素必须有值,我们定义注解元素时,经常使用空字符串,0为默认

  • public class Demo01 {
        @MyAnnotation2(name="nihao",schools="憨批")
        public void test(){}
    }
    
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @interface  MyAnnotation2{
        String name() default"";
        int age() default 0;
        int id() default -1;//如果默认值为-1,代表不存在
        String[] schools() default {"憨批","hape"};
    }
    

反射机制Reflection

反射概述

  • Reflection(反射)java动态语言的关键,允许程序在执行期间借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
  • Class c=Class.forName(“java.lang.String”)
  • 在加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象,这个对象就包含了完整的类的接口信息。

获得反射对象

  • 运行时判断任意一个对象所属的类
  • —构造任意一个类的对象
  • —判断任意一个类具有的成员变量和方法
  • —获取泛型信息
  • —调用任意一个对象的成员变量和方法
  • —处理注解
  • 生成动态代理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-49nUNfZQ-1606403200880)(C:\Users\wuvcky\AppData\Roaming\Typora\typora-user-images\image-20201126110209809.png)]

  • try {
                Class c1=Class.forName("user");
                System.out.println(c1);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
        }
    

获得class对象

  • Class本身也是一个类,Class对象由系统建立

  • 一个加载的类在JVM中只有唯一一个Class实例

  • 一个Class对象对应的是一个加载到JVM中的一个.class文件

  • 每一个类都会记得自己由哪个Class实例生成

  • 通过Class可以完整得到一个类中的所有被加载的结构

  • Class类的常用方法

  • 返回指定类名name的Class对象

 Class c1=Class.forName("user");
 System.out.println(c1);
  • 调用缺省构造函数,返回Class对象的一个实例
 Class c1=user.class;
  Object n=c1.newInstance();
  • 返回当前Class对象的父类的Class对象
Class c2=c1.getSuperclass();
  • 获取当前Class对象的接口
 Class[] c3=c1.getInterfaces();
  • 获得该类的类加载器
ClassLoader c4=c1.getClassLoader();
  • Class类的创建方式

    • Class clasz=Person.class; 最安全可靠,程序性能高
    • Class clasz=person.getClass(); 通过类的实例获得类的Class对象
    • 通过Class类的静态方法forName()获取
    • Class c1=Class.forName(“path”);
      Person person=new Student();
            System.out.println("这个人是"+person.name);
    
         Class c1=person.getClass();
            System.out.println(c1.hashCode());
    
            Class c2=Class.forName("Student");
            System.out.println(c2.hashCode());
    
            Class c3=Student.class;
            System.out.println(c3.hashCode());
    

    三个Class对象会打印出同个hashcode

所有类型的Class对象

  • Class:外部类,成员内部类,静态内部类,局部内部类,匿名内部类
    interface:接口
    []:数组
    enmu:枚举
    annotation:注解@interface
    primitive type:基本数据类型
    void
    
  • 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;
            Class c9=Class.class;
    

类的加载过程

  • Java内存分为堆、栈、方法区,方法区是堆里一个特殊的区域

  • 在堆里面,存放一些new的对象和数组,堆可以被所有的线程共享,不会存放别的对象引用

  • 在栈里面,存放基本变量类型,包含基本类型的具体数值,引用对象的变量(存放这个引用在堆里面的具体地址)

  • 在方法区内,可以被所有的线程共享,包含了所有的class和static变量

  • 类的加载过程:当程序主动使用某个类时,经过三个步骤

  • 类的加载--------------------》类的链接-------------------------》类的初始化

  • (load) (Link) (Initialize)

  • 将类的class文件读入内存,并创建一个java.lang.Class对象,由类加载器完成

  • 将类的二进制数据合并到JRE中

  • JVM负责类的初始化

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TQ6YiEbL-1606403200882)(C:\Users\wuvcky\Desktop\图片\image-20201126154007138.png)]

什么时候发生类的初始化

  • 当虚拟机启动,先初始化main方法所在的类

  • new

  • 调用类的静态成员和静态方法

  • 反射调用

  • 初始化类会先初始化父类

  • 当访问一个静态域时,只有真正声明这个域的类才会被初始化

  • 通过数组定义类引用,不会触发此类的初始化 Person[] person=new Person[10]

  • 引用常量不会触发此类的初始化

类加载器的作用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nZM7qRBB-1606403200883)(C:\Users\wuvcky\AppData\Roaming\Typora\typora-user-images\image-20201126162610386.png)]

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

获取运行时类的对象

  • get()

如何使用

  • 通过Class对象的newInstance()创建一个对象

    类必须有一个无参数的构造器
        类的构造器访问权限必须要够
    
  • 通过反射获得构造器,通过构造器创建一个对象

  •  Class c1=Class.forName("A");
           A a=(A)c1.newInstance();
    
           Constructor cc=c1.getConstructor(int.class);
           A aa=(A)cc.newInstance(19);
    
  • 通过反射获得方法

  •  Method show=c1.getDeclaredMethod("nihao");
            show.invoke(a);
    
  • 通过反射获得属性

  • Field ccc=c1.getDeclaredField("m");
    ccc.set(a,1000);
    System.out.println(a.m);
    
  •  Field ccc=c1.getDeclaredField("m");
            ccc.setAccessible(true);
            ccc.set(a,1000);
            System.out.println(a.getM());
    //操作私有属性 setAccessible
    
  • setAccessible

    Method和Field、Constructor对象都有setAccessible方法
    启动和禁用访问安全检查的开关
    true关闭
    可以提高反射的效率
    
    

通过反射操作泛型

通过Fan.class.getDecLaredMethod获得方法

通过方法c1.getGenericParameterTypes获得泛型数组

如果是参数化类型 强转成参数化类型再输出

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Fan {
    public void fan1(Map<String,user> map, List<String> list, Set<Object> set){
        System.out.println("test1");
    }
    public Map<String,user> nihao(){
        return null;
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method c1=Fan.class.getDeclaredMethod("fan1",Map.class,List.class,Set.class);
        Type[] genericParameterTypes = c1.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);
                }
            }
        }


        System.out.println("-----------------------------------");
        Method c2 = Fan.class.getDeclaredMethod("nihao");
        Type genericReturnType = c2.getGenericReturnType();
        if(genericReturnType instanceof ParameterizedType){
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println(actualTypeArgument);

            }
        }
    }
}

通过反射操作注解

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

public class Table {

    public static void main(String[] args) throws NoSuchFieldException {
        Class c1=StudentTable.class;
     //获取类的对象,反射获得类的注解 强转成注解类型
        myAno myano=(myAno)c1.getAnnotation(myAno.class);
        //将注解的value转成String,打印
        String value = myano.value();
        System.out.println(value);
        System.out.println("--------------------------");
        
        //获取类的属性
        Field f = c1.getDeclaredField("id");
        //通过属性反射出注解 强转成注解类型
        myAnoo annotation = f.getAnnotation(myAnoo.class);
        System.out.println(annotation.len());
        System.out.println(annotation.name());
        System.out.println(annotation.type());
    }
}
@myAno("db_Student")
class StudentTable{
    @myAnoo(name = "id", type = "int", len = 10)
     int id;
    @myAnoo(name = "age", type = "int", len = 10)
    int age;
    @myAnoo(name = "name", type = "String", len = 10)
    String name;

}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface myAno{
    String value();
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface myAnoo{
    String name();
    String type();
    int len();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值