注解和反射

元注解

元注解是负责注解其他注解的注解

@Target:用于描述注解的使用范围(即:被描述的注解可以使用在什么地方)(value={可以有多个值})

@Retention:表示需要在什么等级保存该注解信息,用于描述注解的使用周期(SOURCE<CLASS<RUNTIME)

SOURCE:在源文件中可以用,

CLASS:在.class文件有效

RUNTIME:在运行是可以用(重点)

@Document:说明该注解讲被包含在javadoc中

​ 表示该注解是否生成在javadoc文档当中

@Inherited:说明子类可以继承父类中的该注解

自定义注解

@interface

package com.wc.db;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//注解作用域
@Target(value = {ElementType.TYPE,ElementType.FIELD})
//注解的生命周期
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotaion {
    //这个不是方法而是注解的名字注解的类为string
    String value();
    //注解的默认值是10注解
    int age() default 10;
}

反射机制(reflection)

反射机制使java语言是一个准动态的语言

反射机制允许程序在执行期间借助于reflection API获取任何类的内部信息,并能够直接操作任意对象的内部属性及方法

反射相关的主要API:

​ java.lang.Class:代表一个类

​ java.lang.reflect.Method:代表类的方法

​ java.lang.reflect.Field:代表类的方法

java.lang.reflect.Constructor:代表类的构造器

什么叫反射

一个类在内存中只有一个Class对象

一个类被加载后,整个类的结构都会被封装在Class对象中。

基本类型有特殊的获取class对象的方法:

​ Class 变量名=数据类型.Type;

//一个类咋内存中只有一个class对象
//数据类型对象有特殊的获取class对象的方法

public static void main(String[] args) throws ClassNotFoundException {
    Class aClass = Class.forName("com.wc.dao.imp.BookseleImp");
    BookseleImp bookseleImp = new BookseleImp();
    Class aClass1 = bookseleImp.getClass();
    Class bookseleImpClass = BookseleImp.class;
    Class type = Integer.TYPE;
    System.out.println(type);
    System.out.println(aClass.hashCode());
    System.out.println(aClass1.hashCode());
    System.out.println(bookseleImpClass.hashCode());
}

类加载内存分析

Java内存:

	堆:存放new的对象和数组

​ 栈:存放基本变量类型(包含基本类型的具体数值)

​ 引用对象的变量(存放这个引用在对堆里面的具体地址

类执行:静态的属性和代码块那个写在前面那个先执行

类的主动引用

子类被初始化之前会初始化父类:

​ 实例化B(子类对象之前)会实例化父类对象

​ 1.调用父类的静态代码块,2.在调用子类的静态代码块

​ 3.在调用父类的无参构造器,4.在调用子类的无参构造器

package com.cw.demo01;

public class TestDui {
    public static void main(String[] args) {
        A b = new B();
    }
}

class A{
    static  {
        System.out.println("父类静态代码块");
    }
    public A() {
        System.out.println("父类无参");
    }
}
class B extends A{
    static {
        System.out.println("子类静态代码块");
    }
    static final int c=10;
    public B(){
        System.out.println("子类无参");
    }
}

类的被动引用

通过子类调用父类的静态方法不会初始化子类对象

定义一个子类的数组是,不会给子类对象初始化

调用对象的常量(final)修饰的属性,不会实例化对象(但是如果调用final修饰的方法类会初始化)

public static void main(String[] args) {
    B[] b=new B[5];
    ArrayList<B> bs = new ArrayList<>();
    int b1 = B.b;
     int c = B.c;
}

类加载器的作用

源码.java文件–》Java编译器—》字节码文件.class–》类加载器----》字节码校验器—》解释器----》操作系统平台

package com.cw.demo01;

import java.util.ArrayList;

public class TestDui {
    public static void main(String[] args) throws ClassNotFoundException {

        //获取系统类的加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        //获取类的父类加载器-》扩展加载器
        ClassLoader parent = systemClassLoader.getParent();
        //获取根加载器,无法直接获取
        ClassLoader parent1 = parent.getParent();
        //获取当前类加载器
//        ClassLoader classLoader = Class.forName("com.cw.demo01.TestDui").getClassLoader();
        //获取系统加载器的加载路径
        System.out.println(System.getProperty("java.class.path"));
        /**
         * D:\bangong\Java\jdk-17.0.2\bin\java.exe "-javaagent:
         * D:\Program Files\JetBrains\IntelliJ IDEA 2021.3\lib\idea_rt.jar=49832:
         * D:\Program Files\JetBrains\IntelliJ IDEA 2021.3\bin" -Dfile.encoding=UTF-8 -classpath 
         * D:\projects\emp-sys-mgr\target\classes;
         * C:\Users\Administrator\.m2\repository\org\apache\logging\log4j\log4j-slf4j-impl\2.17.2\log4j-slf4j-impl-2.17.2.jar;
         * C:\Users\Administrator\.m2\repository\org\slf4j\slf4j-api\1.7.25\slf4j-api-1.7.25.jar;
         * C:\Users\Administrator\.m2\repository\org\apache\logging\log4j\log4j-api\2.17.2\log4j-api-2.17.2.jar;
         * C:\Users\Administrator\.m2\repository\org\apache\logging\log4j\log4j-core\2.17.2\log4j-core-2.17.2.jar com.cw.demo01.TestDui
         */
    }
}


反射获取类的属性方法

package com.cw.demo01;

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

public class TestDui {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class aClass = Class.forName("com.cw.demo01.B");
        System.out.println(aClass.getName());//获取路径
        System.out.println(aClass.getSimpleName());//获取类名
        System.out.println(aClass.getPackageName());//获取包名不加类名
        System.out.println(aClass.getTypeName());//获取路径
        System.out.println("======");
        Field[] fields = aClass.getFields();//获得当前类和父类的所有的public属性

        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("====");
        fields = aClass.getDeclaredFields();//获取当前类的所有属性
        for (Field field : fields) {
            System.out.println(field);
        }
        Field insp = aClass.getDeclaredField("insp");//获取当前类的某个属性
        System.out.println("======");
        Method[] methods = aClass.getMethods();//获得当前类的所有的public方法
        for (Method method : methods) {
            System.out.println(method);
//            Class<?>[] parameterTypes = method.getParameterTypes();获取当前方法的参数
//            for (Class<?> parameterType : parameterTypes) {
//                System.out.println("++"+parameterType);
//            }
            Class<?> returnType = method.getReturnType();
            System.out.println(returnType+"++");//获取当前方法的返回值类型
        }
        System.out.println(aClass.getMethod("setId", Integer.class));//获取当前类和父类的指定方法参数为该方法参数类型
        System.out.println("=====");
        methods = aClass.getDeclaredMethods();//获取当前类所有方法
        for (Method method : methods) {
            System.out.println(method);
            Class<?>[] parameterTypes = method.getParameterTypes();//获取当前方法的参数
            for (Class<?> parameterType : parameterTypes) {
                System.out.println("++"+parameterType);
            }
            Class<?> returnType = method.getReturnType();
            System.out.println(returnType+"++");//获取当前方法的返回值类型
        }
        System.out.println("---");
        Constructor[] constructors = aClass.getConstructors();//获取当前类的所有public构造器
//        for (Constructor constructor : constructors) {
//            System.out.println(constructor);
//        }
        constructors = aClass.getDeclaredConstructors();//获取当前类的所有的构造器
        for (Constructor constructor : constructors) {
            Class[] parameterTypes = constructor.getParameterTypes();
           
            System.out.println(constructor);
        }

    }
}

class A {
    public Integer no;
    private Integer id;
    private String name;

    public A() {

    }

    public A(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    private void fun() {

    }

    public void fun(Integer id) {

    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

class B extends A {

    private Integer insp;

    public Integer getInsp() {
        return insp;
    }

    public void setInsp(Integer insp) {
        this.insp = insp;
    }

    public B(Integer id, String name, Integer insp) {
        super(id, name);
        this.insp = insp;
    }

    private B(Integer id, String name) {
        super(id, name);

    }
    public B(String s) {
    }
    public B() {
    }
}

创建运行时类对象

通过反射获取方法

方法. invoke(实例化的对象,值);

(方法是getMethod获取方法)

关闭权限检测

setAccessible(true)关闭安全检测可以使用改变私有的方法和属性

package com.cw.demo01;

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

public class Demo2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        Class<?> aClass = Class.forName("com.cw.demo01.B");
        Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
        String simpleName = aClass.getSimpleName();
        System.out.println(simpleName);
        B o = (B)declaredConstructor.newInstance();
        Method setId = aClass.getMethod("setId", Integer.class);
        setId.invoke(o,123);
       
        System.out.println(o.getId());

    }
}

setAccessible

使用setAccessible(true)

package com.cw.demo01;

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

public class Demo2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        Class aClass = Class.forName("com.cw.demo01.B");
        String simpleName = aClass.getSimpleName();
        Constructor declaredConstructor = aClass.getDeclaredConstructor();
        B o = (B)declaredConstructor.newInstance();
//        o.setInsp(15);
        Method setId = aClass.getMethod("setId", Integer.class);
        setId.invoke(o,15);
        Method getId = aClass.getMethod("getId");
        Object invoke = getId.invoke(o);
        Field name = aClass.getDeclaredField("insp");
        name.setAccessible(true);//使用
        name.set(o,20);

        System.out.println(o.getInsp());
    }
}

反射操作泛型

instanceof判断反射获得类型是否相等

getgenericparametertypes():获取参数的类型

parameterizedType:表示一种参数化类型比如Colection泛型约束

GenericArrayType:表示一种元素类型是参数化类型或者参数化变量的数组类型

TypeVariable:是各种类型变量的公共父接口

WildcardType:代表一种通配符类型表达式

package com.cw.demo01;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.List;

/**
 * 反射获得的参数是否是泛型
 */
public class Demo03 {
    public static HashMap<String, Integer> test01(HashMap<String,Demo03> map, List<Integer> list){
        return null;
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Class c1 = Demo03.class;
        Method t1 = c1.getMethod("test01", HashMap.class, List.class);
        //获取方法的形参
        Type[] genericParameterTypes = t1.getGenericParameterTypes();
        for (Type genericParameterType : genericParameterTypes) {
            if (genericParameterType instanceof ParameterizedType) {
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {

                    System.out.println(actualTypeArgument);
                }
            }
            else{
                System.out.println(genericParameterType+"else");
            }
        }
    }
}

反射操作注解

注意:反射对象.getAnnotation(注解类)是获取当前对象的注解,

如果想要获得值可以:反射对象.getAnnoataion(注解类).value()------此处的value()就相当于注解的属性

package com.cw.demo01;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;

@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
@MyInterface("我的自定义")
public class MyAnnotationRef {
    @MyInterfaceTwo("wpde")
    private Integer id;

    public static void main(String[] args) throws NoSuchFieldException, ClassNotFoundException {
        
        
        Class c1 = MyAnnotationRef.class;//反射获取类对象
        Field id = c1.getDeclaredField("id");//获取类对象的属性
        //获取属性的某个值,括号内就是某个值的注解类
        MyInterfaceTwo annotation = id.getAnnotation(MyInterfaceTwo.class);
        System.out.println(annotation.length());//获取注解的值
        System.out.println(annotation.value());
        //获取当前类的对象
        MyInterface myann = (MyInterface) c1.getAnnotation(MyInterface.class);
        //获取类对象的值
        System.out.println(myann.value());
    }
}

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


@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyInterfaceTwo {
    String value() default "默认";

    int length() default 10;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值