IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 学习总结:Java的注解、类加载、反射 -> 正文阅读

[Java知识库]学习总结:Java的注解、类加载、反射

注解

JDK5.0引入。和注释一样,都是用来解释说明代码的,区别就是注释是给程序员看的,注解是给程序看的。添加注解就相当于给代码添加了辅助信息,这些辅助信息可以通过反射来访问。

内置注解

常用的内置注解有三个
1、@Override:重写方法
2、@Deprecated:表明不推荐使用,但是依然可以使用
3、@SuppressWarnings:镇压警告,需要传参数。

元注解

元注解的作用就是:注解其他的注解,相当于解释其他注解的作用,Java定义了四种meta-annotation类型的注解
1、@Target:描述注解的适用范围
2、@Retention:描述注解的生命周期,表示在什么级别保存注解
3、@Document:说明注解会被包含在javadoc种
4、@Inherited:说明子类可以继承父类的注解

自定义注解

public class Test1 {
    @MyAnnotation("")
    public void test() {}

    @MyAnnotation2(name = "")
    public void test1(){}

    @MyAnnotation3(name = "",person = {"清华"})
    public void test3(){}

}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@interface MyAnnotation{
    String value();//表示使用时需要传入一个String
    // 如果只有一个参数,一般使用value
}

@interface MyAnnotation2{
    String name();//如果不使用value,使用时就需要写出 name =
}
@interface MyAnnotation3{
    int age() default -1;//可以设定默认值,-1代表不存在
    String name() ;
    String[] person();
}

类加载

当一个类被使用的时候,就需要加载类。过程可以分为三个阶段。

加载

1、获取类的二进制字节流
2、把字节流代表的静态结构转换成运行时数据结构
3、在堆生成该类的Class对象

链接

1、验证字节流中的信息是否符合虚拟机安全规范
2、为类变量(static)分配内存并设置初始值
3、将常量池中的符号引用常量替换为直接引用常量

初始化

执行类构造器方法,编译器自动收集类中所有类变量的赋值动作和静态语句块中的语句,然后合并产生的方法。
这里是类构造器,并不是构造器,比如直接输出静态变量的话,并不会执行构造器。
当类被主动引用是会发生初始化:
1、虚拟机启动会直接初始化main方法所在类。
2、new一个对象时,对象的类会被初始化
3、调用类的静态变量和静态方法(调用静态常量不会)
4、反射
5、初始化类时,如果父类没被初始化过,会先初始化父类
被动引用时不会初始化
1、访问静态领域时,只有这个属性在的类会被初始化。比如子类访问父类的静态变量,只有父类被初始化了
2、数组定义类引用,不会初始化
3、引用常量不会

类加载器

负责类的加载。从上到下分为根加载器、扩展加载器、系统加载器、自定义加载器。
类加载器默认采用双亲委派机制加载。也就是加载一个类的时候,先从下到上寻找,如果已经加载过就不加载;如果找到了根加载器却依然没发现加载,就从根加载器开始判断是否能加载,如果能就加载,如果不能就看子类能否加载。
这个机制的作用是为了防止危险代码。比如我自己写了一个java.lang.String,这个类在被加载时,系统会发现,本身就有String类并且已经加载过了,就不会使用这里面的内容。

反射

反射就是可以在程序运行的时候得到类的内部信息,并通过这个去操纵属性和对象。
在一个类被加载后,堆里就出现了该类的Class对象,这个对象包含了类的所有信息,反射就是通过获取这个对象,从而操纵这个类的信息。每个类的Class对象都是独一的。
通过反射可以使得本来是静态语言的Java拥有了一定的动态性,但是降低了性能。

作用

1、在运行时创建对象
2、在运行时判断对象属于哪个类
3、在运行时获取泛型信息
4、在运行时判断某个类是否具有某些成员变量以及方法
5、在运行时调用对象的属性和方法
6、动态代理
7、等等

获取反射对象

public class Test2 {
    public static void main(String[] args) throws ClassNotFoundException {
        //1、通过对象获得
        Student s =new Student();
        Class c = s.getClass();
        //2、通过forname
        Class c1 = Class.forName("Student");
        //3、通过class属性,最高效
        Class c2 = Student.class;
        //4、内置类
        Class c3 = Integer.TYPE;
        //获得父类对象类型
        Class c4 = c.getSuperclass();
    }
}
class Person{
    
}
class Student extends Person{
    
}

拥有Class对象的类型

public class Test3 {
    public static void main(String[] args) {
        //每种类型只有一个对象。比如数组就算长度不同,
        //但是维度和类型一样,得到的是一样的
        Class c1 = Object.class;//类
        Class c2 = Runnable.class;//接口
        Class c3 = Override.class;//注解
        Class c4 = ElementType.class;//枚举
        Class c5 = String[].class;//一维数组
        Class c6 = int[][].class;//二维数组
        Class c7 = void.class;//void
        Class c8 = Class.class;//Class
        Class c9 = Integer.class;//基本数据类型
	}
}

通过反射对象获取类的信息

public class Test6 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException {
        Class c = Class.forName("User");
        //获取类名
        c.getName();//包名+类名
        c.getSimpleName();//类名
        //获取属性
        Field[] pFields = c.getFields();//找到public属性
        Field[] aFields = c.getDeclaredFields();//可以找到所有属性
        c.getField("name");//获取指定属性
        //获得方法
        Method[] pMethod = c.getMethods();//获得本类和父类的所有public
        Method[] aMethod = c.getDeclaredMethods();//获得本类的所有方法
        c.getMethod("setAge", int.class);//获得指定方法,需要传入参数类型的Class,因为可能方法有重载
        //获得构造器
        Constructor[] pConstructor = c.getConstructors();//获得本类public
        Constructor[] aConstructor = c.getDeclaredConstructors();//获得本类所有
        c.getDeclaredConstructor(String.class,int.class,int.class);//获得指定构造器,同理
    }
}
class User{
    private int age;
    private int id;
    private String name;

    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public User(int age, int id, String name) {
        this.age = age;
        this.id = id;
        this.name = name;
    }
     public User() {
    }

}

通过反射对象创建对象,执行方法,操作属性

public class Test7 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        //获得User的Class对象
        Class c = Class.forName("User");
        //通过构造器创建对象
        Constructor aConstructor =c.getDeclaredConstructor(int.class,int.class,String.class);
        User u1 = (User) aConstructor.newInstance(20,10001,"Jim");
        System.out.println(u1);//User{age=20,id=10001,name='Jim'}
        //调用无参构造创建User对象
        User u = (User) c.newInstance();//调用的是无参构造器,如果没有设置无参构造,会报错
        //获取方法
        Method aMethod = c.getDeclaredMethod("setName", String.class);
        aMethod.invoke(u,"Jerry");
        System.out.println(u.getName());//Jerry
        //操作属性
        Field aAge = c.getDeclaredField("age");
        aAge.setAccessible(true);//关掉权限检测,否则访问私有属性会报错
        aAge.set(u,20);
        System.out.println(u.getAge());//20
    }
}

通过反射对象获取泛型信息

public class Test8 {
    public static void test1(Map<String,User> map, List<User> list){
        System.out.println("test1");
    }
    public static Map<String,User> test2(){
        System.out.println("test2");
        return null;
    }

    public static void main(String[] args) throws NoSuchMethodException {
        //获取Class对象
        Class c = Test8.class;
        //获取方法
        Method m1 = c.getDeclaredMethod("test1", Map.class, List.class);
        //获取Map,List的泛型
        Type[] t1 = m1.getGenericParameterTypes();
        for (Type type : t1) {
            System.out.println("==" + type + "==");
            //获取Map,List内部数据的泛型
            if (type instanceof ParameterizedType){
                Type[] t11 = ((ParameterizedType) type).getActualTypeArguments();
                for (Type type1 : t11) {
                    System.out.println(type1);
                }
            }
        }
        //获取方法
        Method m2= c.getDeclaredMethod("test2",null);
        //获取方法的返回值泛型
        Type t2 = m2.getGenericReturnType();
        System.out.println("-----" + t2 + "-----");
        //获取Map里数据的返回值泛型
        if (t2 instanceof ParameterizedType){
            Type[] t22 = ((ParameterizedType) t2).getActualTypeArguments();
            for (Type type : t22) {
                System.out.println(type);
            }
        }
    }
}

通过反射获取注解信息

public class Test9 {
    public static void main(String[] args) throws NoSuchFieldException {
        //获取对象
        Class c = Teacher.class;
        Annotation[] a = c.getAnnotations();
        //找到注解-----ClassInterface
        for (Annotation annotation : a) {
            System.out.println(annotation);
        }
        //找到注解的值-----class
        ClassInterface f = (ClassInterface) c.getAnnotation(ClassInterface.class);
        String value = f.value();
        System.out.println(value);

        //找到指定的注解----length和name的值
        Field field = c.getDeclaredField("age");
        FieldInterface fieldInterface = field.getAnnotation(FieldInterface.class);
        System.out.println(fieldInterface.length());
        System.out.println(fieldInterface.name());


    }
}
@ClassInterface("class")
class Teacher{
    @FieldInterface(length = 3,name = "age")
    private int age;
    @FieldInterface(length = 4,name = "name")
    private String name;

    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;
    }

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

    public Teacher() {
    }
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface ClassInterface{
    String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldInterface{
    int length();
    String name();
}
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-16 22:07:36  更:2022-03-16 22:10:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:00:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码