[Java] annotations and reflection

1. What is annotation

  1. Annotation is a new technology introduced from JDK5.0.

  1. The role of Annotation:

Not the program itself, you can explain the program (this is no different from the comment comment)

Can be read by other programs (eg: compiler) .

  1. Annotation format

The annotation exists in the code with "@ annotation name", and some parameter values ​​can also be added,

For example:

@SuppressWarnings(value="unchecked")

  1. Where is Annontation used?

It can be attached to packages, classes, methods, fields, etc., which is equivalent to adding additional auxiliary information to them. We can program to access these metadata through the reflection mechanism.

2. Built-in annotations

  1. @Override: Defined in java.lang.Override, this annotation is only applicable to modified methods, indicating that a method declaration intends to override another method declaration in the superclass.

  1. @Deprecated: Defined in java.lang.Deprecated, this annotation can be used to decorate methods, properties, and classes, indicating that programmers are discouraged from using such elements, usually because it is dangerous or there are better options.

  1. @SuppressWarnings: Defined in java.lang.SuppressWarnings, used to suppress warning messages at compile time.

Different from the previous two comments, you need to add a parameter to use it correctly. These parameters are already defined, and you can use them selectively:

@SuppressWarnings("all")

@SuppressWarnings("unchecked")

@SuppressWarnings(value={"unchecked","deprecation"})

......

import java.util.List;

//什么是注释
public class Test01 extends Object{
    //@Override    重写的注解
    @Override
    public String toString() {
        return super.toString();
    }

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

    //@SuppressWarnings("all")     镇压全部警告
    @SuppressWarnings("all")
    public void test02(){
        List list = new ArrayList();
    }
    public static void main(String[] args) {
        test();
    }
}

3. Meta annotations

  1. The role of meta-annotation is to annotate other annotations. Java defines 4 standard meta-annotation types, which are used to provide explanations for other annotation types.

  1. These types and the classes they support are found in the java.lang.annotation package. ( @Target , @Retention , @Documented , @Inherited )

(1) @Target: Used to describe the usage scope of annotations (that is, where the described annotations can be used)

(2) @Retention: indicates at what level the annotation information needs to be saved, and is used to describe the life cycle of the annotation

(SOURCE < CLASS < RUNTIME

(3) @Document: Indicates that the annotation will be included in javadoc

(4) @Inherited: Indicates that the subclass can inherit the annotation in the parent class

import java.lang.annotation.*;

//测试元注解
public class Test02 {
    @MyAnnotation
    public void test(){
    }

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

//Retention    表示注解在什么地方有效
//   runtime > class > sources
@Retention(value = RetentionPolicy.RUNTIME)

//Documented   表示是否将注解生成在JavaDoc中
@Documented

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

@interface MyAnnotation{
}

4. Custom annotations

When using @interface custom annotation, it automatically inherits the java.lang.annotation.Annotation interface.

Analysis:
@interface is used to declare an annotation, format: public @interface annotation name {definition content}
Each method in it actually declares a configuration parameter.
The name of the method is the name of the parameter.
The return value type is the type of the parameter, and the return value can only be the basic type (Class, String, enum).
The default value of the parameter can be declared by default.
If there is only one parameter member, the general parameter name is value.
Annotation elements must have a value. When we define annotation elements, we often use the empty string 0 as the default value.
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

//自定义注解
public class Test03 {
    //注解可以用default显示赋值,如果没有默认值,就必须给注解赋值
    @MyAnnotation2(name = "张三",schools = {"京大","南大"})
    public void test(){
    }

    @MyAnnotation3("张三")
    public void test2(){
    }
}
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
    //注解的参数 : 参数类型 + 参数名();
    String name();
    int age() default 0;
    int id() default -1; //如果默认值为-1,代表不存在    (indexof ,如果找不到就返回-1)

    String[] schools();
}

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation3{
    //如果只有一个参数,使用value赋值
    String value();
}

5. Reflection mechanism

  1. static language and dynamic language

(1) Dynamic language

It is a language whose structure can be changed at runtime: for example, new functions, objects, and even code can be introduced, existing functions can be deleted or other structural changes. In layman's terms, the code can change its structure according to certain conditions at runtime.

Main dynamic languages: Object-C, C#, JavaScript, PHP, Python, etc.

When using the JavaScript language, the value of X can be changed at runtime.

(2) Static language

Corresponding to dynamic languages, languages ​​with immutable operating structures are static languages.

Such as Java, C, C++.

Java is not a dynamic language, but Java can be called a "quasi-dynamic language". That is, Java has a certain degree of dynamism, and we can use the reflection mechanism to obtain characteristics similar to dynamic languages. The dynamic nature of Java makes programming more flexible.

  1. reflection

Reflection (reflection) is the key to Java being regarded as a dynamic language. The reflection mechanism allows the program to obtain the internal information of any class by means of the Reflection API during execution , and can directly manipulate the internal properties and methods of any object.

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

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

Java反射机制提供的功能
在运行时判断任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时获取泛型信息
在运行时调用任意一个对象的成员变量和方法
在运行时处理注解
生成动态代理

优点:

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

缺点:

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

反射相关的API:
java.lang.Class : 代表一个类
java.lang.reflect.Method:代表类的方法
java.lang.reflect.Field:代表类的成员变量
java.lang.reflect.Constructor:代表类的构造器

2.1 Class类

在Object类中定义了以下方法,此方法将被所有子类继承:

public final Class getClass()

以上的方法返回值的类型是一个Class类,此类是Java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称。

对象照镜子(反射)后可以得到的信息:某个类的属性,方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE都为其保留一个不变的Class类型的对象。一个Class对象包含了特定的某个结构的有关信息。

Class本身也是一个类
Class对象只能由系统建立对象
一个加载在类在JVM中只会有一个Class的实例
一个Class对象对应的是一个加载到JVM中的一个.class文件
每个类的实例都会记得自己是由哪个Class实例所生成
通过Class可以完整地得到一个类中的所有被加载的结构
Class类是Reflection的根源,针对任何你想动态加载、运行的类,唯有先获得相对应的Class对象

2.1.1 Class类的常用方法:

2.1.2 获取Class类的实例

(1)若已知具体的类,通过类的class属性获取,该方法作为安全可靠,程序性能最高。

Class clazz = Person.class;

(2)已知某个类的实例,调用该实例放入getClass()方法获取Class对象

Class clazz = person.getClass();

(3)已知某个类的全类名,且该类在类路径下,可通过Class的静态方法forName()获取,可能抛出ClassNotFoundException

Class clazz = Class.forName("demo01.Student");

(4)内置基本数据类型可以直接用类名.Type

(5)还可以利用ClassLoader

package com.reflection;
//测试Class类的创建方式有哪些
public class Test03 {
    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<Student> 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(String name) {
        this.name = name;
    }

    public Person() {
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}
class Student extends Person{
    public Student() {
        this.name="学生";
    }
}
class Teacher extends Person{
    public Teacher() {
        this.name="老师";
    }
}

2.1.3 哪些类型可以有Class对象

class:外部类,成员(成员内部类、静态内部类),局部内部类、匿名内部类。

interface:接口

[]:数组

enum:枚举

annotation:注解@interface

primitive type:基本数据类型

void

package com.reflection;

import java.lang.annotation.ElementType;

//所有类型的Class
public class Test04 {
    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());
    }
}

2.2Java的内存分析

堆:存放

未完待续!!!

Guess you like

Origin blog.csdn.net/yao_yaoya/article/details/128534979