注解与反射 深入ing!

Annotation的格式

idea 编译器中黄色的代码(@注释名)

Annotation的作用:

不是程序本身,可以对程序作出解释。(这一点和注释相同)

可以被其他程序读取。

Annotation在那里使用

可以附加在包、类、方法上,相当于给他们添加了额外的辅助信息,我们可以通过反射机制编程实现对这些元素据的访问

内置注解

@Overide //重写一个类的方法

@Deprecated //不推荐使用此方法,有更好的方法或替代

@SuppressWarnings //用来抑制编译时的警告信息
//要有参数(all) (unchecked) (value={"unchecked","depreciation"})

元注解

作用就是负责注解其他注解(@Target@Retention,@Documented,@Inherited)

@MyAnnotation
public class Test01 {
    public void test(){
        
    }
}


//定义一个注解
//Target 表示我们的注解可以用在哪些地方
@Target(value = {ElementType.METHOD,ElementType.TYPE})

//Rectention 表示我们的注解在什么地方有效
//runtime > class > sources(Java源码中)
@Retention(value = RetentionPolicy.RUNTIME)

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

//Inherited 子类可以继承父类的注解
@Inherited
@interface MyAnnotation{//自定义注解

}

自定义注解

使用@interface 自定义注解

//自定义注解
public class Test02 {
    @MyAnnotation2(age=18,name="xzh")
    public void test(){}

    @MyAnnotation3("xzh")//value可以不写出
    public void test2(){}

}


@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
    //注解参数:参数类型 + 参数名();
    String name() default "";
    int age();
    int id() default -1;//如默认值是-1,代表不存在

    String[] schools() default {"西华大学","清华大学"};
}

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation3{
    String value();//只有一个值时,
    // 用value可以在方法上面不加value直接赋值
}

反射机制

Java有一定的动态性,我们可以利用反射机制获得类似动态语言的特性。

优点:

可以实现动态创建对象和编译,体现出很大的灵活性

缺点:

对性能有影响。使用反射基本上是一种解释操作,告诉JVM,我们希望做什么并且它满足我们的需求。总是慢于 直接执行相同的操作

认识反射
//什么叫反射
public class Test01 {
    public static void main(String[] args) throws ClassNotFoundException {
        //通过反射获取类的class对象
        Class c1 = Class.forName("reflection.User");
        System.out.println(c1);

        Class c2 = Class.forName("reflection.User");
        Class c3 = Class.forName("reflection.User");
        Class c4 = Class.forName("reflection.User");

        //一个类在内存中只有一个Class对象
        //一个类被加载后,类的整个结构都会被封装在Class对象中
        System.out.println(c2.hashCode());
        System.out.println(c3.hashCode());
        System.out.println(c4.hashCode());
    }

}

//实体类:pojo  ,entity
class User{
    private String name;
    private int id;
    private int age;
}
获取class对象
//4种方式
 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("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);
    }
/*
这个人是:学生
1163157884
1163157884
1163157884
int
class reflection.Person
*/

哪些类型可以有Class对象

几乎所有类型都有Class对象

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(c8);
        System.out.println(c9);

        //只要元素类型与维度一样,就是同一个CLass
        int[] a=new int[10];
        int[] b=new int[100];
        System.out.println(a.getClass().hashCode());
        System.out.println(b.getClass().hashCode());
    }
/*
class java.lang.Object
interface java.lang.Comparable
class [Ljava.lang.String;
class [[I
interface java.lang.Override
class java.lang.annotation.ElementType
class java.lang.Integer
void
class java.lang.Class
1163157884
1163157884

*/
类加载内存分析
/*
1.加载到内存,会产生一个类对应的Class对象
2.链接,链接结束后 变量赋值默认为m=0
3.初始化
	<clinit>(){
	}//使用clinit方法初始化static代码,将static代码放入此方法中
*/
类初始化

Main类->父类->子类

类的初始化还要分类的主动引用被动引用

类加载器

作用是用来把类class装载进内存的。JVM规范定义了如下类型的类的加载器。

引导加载器:JVM自带的类加载器

扩展类加载器:jre/lib/ext下单jar包的加载

系统类加载器:负责 Java -classpath所指目录下的类与jar包装入工作,最常用

双亲委派机制:查找包,如果自己创建的与系统的包同名,只执行系统的包,保证安全性。

获取运行时类的完整结构

通过反射获取运行时类的完整结构

Field、Method、Constructor、Superclass、Interface、Annotation

直接调用Class的方法就OK

本人学习Java的一片私人空间……
原文地址:https://www.cnblogs.com/none-space/p/14130556.html