[java学习笔记]-注解和反射


注解

@Override  规则和约束

@Deprecated 危险的方法,过时的方法

@SuppressWarnings 抑制编译时的警告信息

@Override

public class Test1 {

    //@Override是重写的注解
    
    @Override
    public String toString() {
        return super.toString();
    }
}

@Deprecated

//Deprecated不推孝程序员使用,但是可以使用。或者存在更好的方式
@Deprecated
public static void test(){
    System.out.println("Deprecated");
}

@SuppressWarnings

@SuppressWarnings("all")
public void test1(){
    List list = new ArrayList();
}

元注解

@Documented
@Target()
@Retention()
@Inherited

在这里插入图片描述

定义一个注解

//定义一个注解
public @interface MyAnnotation{
}

把注解的范围限制在方法

//类注解
@MyAnnotation
public class Test2 {
    //方法注解
    @MyAnnotation
    public void test(){
    }
}

//定义一个注解
@Target(value = {ElementType.METHOD,ElementType.TYPE})
@interface MyAnnotation{
}
//Retention表示我们的注解在什么地方还有效。
//runtime>class>source
@Retention(value = RetentionPolicy.RUNTIME)
@interface MyAnnotation{
}

//Documented表示是否将我们的注解生成在JAVAdoc中
@Documented

//子类可以继承父类的注解
@Inherited

自定义注解

关键字 @interface

在这里插入图片描述

多参数

public class Test2 {
    //注解可以显示赋值,如果没有默认值,我们就必须给注解赋值
    @MyAnnotation(name = "Muz1")
    public void test(){
    }
}

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
    //注解的参数: 参数类型 + 参数名();
    String name() default "";
    int age() default 0;
    int id() default -1;//如果默认值为-1,代表不存在,indexof,如果找不到就返回-1
    String[] schools() default {"牛马大学","说唱带专"}
}

单参数

public class Test2 {
    //注解可以显示赋值,如果没有默认值,我们就必须给注解赋值
    @MyAnnotation("Muz1")
    public void test(){
    }
}

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
    String[] value();
}

参数名是 value() 可以省略注解参数


反射

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

Class c = Class.forName("java.lang.String");

加载完类之后,在堆内存的方法区中就产生了已个Class类型的对象(一个类只有一个Class对象) ,这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子, 透过这个镜子看到类的结构,所以,我们形象的称之为:反射

在这里插入图片描述

获取一个简单反射

//Test.java

//反射
public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
        //通过反射获取类的Class对象
        Class c1 = Class.forName("com.Reflection.User");
        System.out.println(c1);
    }
}
//实体类 pojo entity
class  User{
    private String name;
    private int id;
    private int age;
    public User(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 "User{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", age=" + age +
                '}';
    }
}

在这里插入图片描述

可以看到这个类有很多方法

在这里插入图片描述


获取其他的类

//Test.java
public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
        //通过反射获取类的Class对象
        Class c1 = Class.forName("com.Reflection.User");
        System.out.println(c1);

        Class c2 = Class.forName("com.Reflection.User");
        Class c3 = Class.forName("com.Reflection.User");
        Class c4 = Class.forName("com.Reflection.User");
        System.out.println(c2.hashCode());
        System.out.println(c3.hashCode());
        System.out.println(c4.hashCode());
    }
}

......

在这里插入图片描述

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

测试class类的创建方式有哪些

package com.Reflection;
//测试Class类的创建方式有哪些
public class Test1 {
    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("com.Reflection.Student");
        System.out.println(c2.hashCode());
        
        //方式三: 通过类名.class获得
        Class c3 = Student.class;
        System.out.println(c3.hashCode());
        
        //方式四: 基本内置类型的包装类都有一个Type属性
        Class c4 = Integer.TYPE;
        System.out.println(c4);

        //获得父类类型
        Class c5 = c1.getSuperclass();
        System.out.println(c5);
    }
}

class Person{
    public String name;
    public Person() {
        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对象

在这里插入图片描述

//Test2.java

package com.Reflection;
import java.lang.annotation.ElementType;

//所有类型的Class
public class Test2 {
    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

        System.out.println("类: " + c1);
        System.out.println("接口: " + c2);
        System.out.println("一维数组: " + c3);
        System.out.println("二维数组: " + c4);
        System.out.println("注解: " + c5);
        System.out.println("枚举: " + c6);
        System.out.println("基本数据类型: " + c7);
        System.out.println("void: " + c8);
        System.out.println("Class: " + c9);
    }
}

在这里插入图片描述


类加载内存分析

在这里插入图片描述

小测试

//Test3.java
package com.Reflection;
public class Test3 {
    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 = 100;
    public A() {
        System.out.println("A类的无参构造器初始化");
    }
}

在这里插入图片描述

在这里插入图片描述

1.加载到内存,会产生一个类对应的class对象
2.链接,链接结束后 m = 0
3.初始化
     <clinit>(){
                 System.out.println("A类静态代码块初始化");
                 m = 300;
                 m = 100;
     }
      m = 100;
     

分析类的初始化

在这里插入图片描述
Demo

Test4.java

package com.Reflection;
//测试类什么时候会初始化
public class Test4 {
    static {
        System.out.println("main类被加载");
    }
    public static void main(String[] args) {
    }
}
class Father{
    static int b = 2;
    static {
        System.out.println("父类被加载");
    }
}
class Son extends Father{
    static {
        System.out.println("子类被加载");
        m = 300;
    }
    static int m = 100;
    static final int M = 1;
}

然后在main方法中加入

public static void main(String[] args) {
    //1.主动引用
    Son son = new Son();
}

输出

在这里插入图片描述

反射

public static void main(String[] args) throws ClassNotFoundException {
    //反射也会产生主动引用
    Class.forName("com.Reflection.Son");
}

输出

在这里插入图片描述

在这里插入图片描述

不会产生类的引用方法

public static void main(String[] args) {
    //不会产生类的引用方法
    System.out.println(Son.b);
}

在这里插入图片描述

数组

public static void main(String[] args) {
    Son[] array = new Son[5];
}

在这里插入图片描述

常量

public static void main(String[] args) {
    System.out.println(Son.M);
}

在这里插入图片描述


类加载器的作用

在这里插入图片描述

在这里插入图片描述

类加载器

package com.Reflection;
public class Test5 {
    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 c1 = Class.forName("com.Reflection.Test5").getClassLoader();
        System.out.println(c1);
        
        //测试JDK内置的类是谁加载的
        ClassLoader c2 = Class.forName("java.lang.Object").getClassLoader();
        System.out.println(c2);
        
        //如何获得系统加载器可以加载的路径
        System.out.println(System.getProperty("java.class.path"));
    }
}

在这里插入图片描述


创建运行时类的对象

之前的 User类

//Test6.java
//获得类的信息
public class Test6 {
    public static void main(String[] args) throws ClassNotFoundException {
        Class c1 = Class.forName("com.Reflection.User");
        //获得类的名字
        System.out.println(c1.getName());
        System.out.println(c1.getSimpleName());
    }
}

在这里插入图片描述

获得类的属性

//Test6.java
public class Test6 {
    public static void main(String[] args) throws ClassNotFoundException {
        Class c1 = Class.forName("com.Reflection.User");

        //获得类的属性
        Field[] fields = c1.getFields();    //只能找到public属性
        
        fields = c1.getDeclaredFields();    //能找到所有的属性
        for (Field field : fields) {
            System.out.println(field);
        }
        //获得指定属性的值
        Field name = c1.getDeclaredField("name");
        System.out.println(name);
    }
}

在这里插入图片描述

//Test6.java
public class Test6 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        
        Class c1 = Class.forName("com.Reflection.User");
        
        //获得类的方法
        //获得本类及其父类的全部public方法
        Method[] methods = c1.getMethods();
        
        for (Method method : methods) {
            System.out.println("正常的: " + method);
        }
        
        //获得本类的所有方法
        methods = c1.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println("getDeclaredMethods: " + method);
        }
    }
}

在这里插入图片描述

获得指定的方法

//Test6.java
public class Test6 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class c1 = Class.forName("com.Reflection.User");
        
        //获得指定的方法
        Method getNames = c1.getMethod("getName", null);
        Method setNames = c1.getMethod("setName", String.class);
        System.out.println(getNames);
        System.out.println(setNames);

    }
}

在这里插入图片描述


动态创建对象执行的方法

通过反射动态的创建对象

//Test7.java

//通过反射动态的创建对象
public class Test7 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        //获得Class对象
        Class c1 = Class.forName("com.Reflection.User");
        //构造一个对象
        User user = (User)c1.newInstance();     //本质上调用了类的无参构造器
        System.out.println(user);
    }
}

在这里插入图片描述

User类无参构造器删除

在这里插入图片描述

再次运行报错

在这里插入图片描述

使用newInstance()函数创建函数,必须有无参构造器

通过构造器创建对象

//Test7.java
//通过构造器创建对象
Constructor c2 = c1.getDeclaredConstructor(String.class, int.class, int.class);
Object muz1 = c2.newInstance("Muz1", 1, 0);
System.out.println(muz1);

在这里插入图片描述

通过反射调用普通方法

//通过反射调用普通方法
User user = (User)c1.newInstance();
//通过反射获取一个方法
Method setName = c1.getDeclaredMethod("setName", String.class);
setName.invoke(user,"Muz1");
System.out.println(user.getName());

在这里插入图片描述

通过反射操作属性

//通过反射操作属性
User user1 = (User)c1.newInstance();
Field name = c1.getDeclaredField("name");
name.set(user1,"Muz12");
System.out.println(user1.getName());

在这里插入图片描述

输出报错,因为 User类里面都是 private 方法

在这里插入图片描述

添加一行代码

//name.setAccessible(true);

User user1 = (User)c1.newInstance();
Field name = c1.getDeclaredField("name");

//不能直接操作私有属性,需要关闭程序安全检测
name.setAccessible(true);

name.set(user1,"Muz12");
System.out.println(user1.getName());

在这里插入图片描述

成功输出


性能对比分析

Demo

三种方式的性能表现

package com.Reflection;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//分析性能问题
public class Test8 {

    //普通方式
    public static void test1(){
        User user = new User();
        long startTime = System.currentTimeMillis();
        for(int i = 0; i < 1000000000; i++){
            user.getName();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("普通方式执行10亿次"+(endTime-startTime)+"ms");
    }
    //反射方式
    public static void test2() 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 < 1000000000; i++){
            getName.invoke(user,null);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("反射方式执行10亿次"+(endTime-startTime)+"ms");
    }

    //反射方式,关闭检测
    public static void test3() 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 < 1000000000; i++){
            getName.invoke(user,null);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("反射方式,关闭检测执行10亿次"+(endTime-startTime)+"ms");
    }
    public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
        test1();
        test2();
        test3();
    }
}

在这里插入图片描述


获取泛型信息

在这里插入图片描述

Demo

//Test9.java
package com.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 Test9 {
    public void test1(Map<String,User> map, List<User> 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 = Test9.class.getMethod("test1", 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);
                }
            }
        }
        
        System.out.println("========================================");
        
        method = Test9.class.getMethod("test2",null);
        Type genericReturnType = method.getGenericReturnType();
        if(genericReturnType instanceof ParameterizedType){
            Type[] actualTypeArguments = ((ParameterizedType)genericReturnType).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println(actualTypeArgument);
            }
        }
    }
}

在这里插入图片描述


获取注解信息

Demo

//Test10.java

package com.Reflection;
import java.lang.annotation.*;
//联系反射操作注解
public class Test10 {
    public static void main(String[] args) throws ClassNotFoundException {
        Class c1 = Class.forName("com.Reflection.Student2");
        //通过反射获得注解
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
    }
}

@AbbMuz1("db_Student")
class Student2{
    @BbbMuz1(columnName = "db_id",type = "int" ,length = 10)
    private int id;
    @BbbMuz1(columnName = "db_age",type = "int" ,length = 10)
    private int age;
    @BbbMuz1(columnName = "db_name",type = "varchar" ,length = 10)
    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 AbbMuz1{
    String value();
}
//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface BbbMuz1{
    String columnName();
    String type();
    int length();
}

获得注解输出

在这里插入图片描述

获得注解value的值

在main方法中添加

//获得注解value的值
AbbMuz1 annotation = (AbbMuz1)c1.getAnnotation(AbbMuz1.class);
String value = annotation.value();
System.out.println(value);

在这里插入图片描述

获得类指定的注解

在main方法中添加

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

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值