Heim > Java > javaLernprogramm > So verwenden Sie Anmerkungen und Reflexion in Java

So verwenden Sie Anmerkungen und Reflexion in Java

王林
Freigeben: 2023-05-10 14:04:06
nach vorne
1285 Leute haben es durchsucht

1. Anmerkung

1.1 Was ist Anmerkung

Anmerkungen sind nicht das Programm selbst und können während der Programmkompilierung, beim Laden der Klasse und zur Laufzeit gelesen werden Verarbeitung. Das Format der Annotation ist „@annotation name (Parameterwert)“, das an Pakete, Klassen, Methoden und Felder angehängt werden kann, und auf die Annotation kann über den Reflexionsmechanismus zugegriffen werden.

1.2 Integrierte Anmerkung

@Override: Unterklassen-Überschreibungsmethode einschränken

Diese Anmerkung zeigt an, dass die Überschreibung erfolgt ist Methoden ihrer übergeordneten Klasse, stellen Sie sicher, dass die Unterklasse tatsächlich die Methode der übergeordneten Klasse überschreibt, um Fehler auf niedriger Ebene zu vermeiden

/**
 * 该注解标识覆盖的是其父类的方法,当子类重写父类方法时,确保子类确实重写了父类的方法,避免出现低级错误
 * @return
 */
@Override
public String toString() {
    return super.toString();
}
Nach dem Login kopieren

@ Veraltet: Als veraltet markiert

Diese Anmerkung weist darauf hin, dass eine Eigenschaft, Methode oder Klasse veraltet ist (ein Programmelement, von dessen Verwendung Programmierern abgeraten wird, normalerweise weil es gefährlich oder besser ist). Wenn eine alternative Methode vorhanden ist, gibt der Compiler eine Warnung (durchgestrichen) aus, wenn andere Programme veraltete Eigenschaften, Methoden oder Klassen verwenden.

/**
 * 该注解表示此方法已过时,存在危险,不推荐使用,其有代替方法,如果继续使用会通过删除线进行标识
 */
@Deprecated
public static void test() {
    System.out.println("标记已过时");
}
Nach dem Login kopieren

@SuppressWarnings(parameter): Compiler-Warnungen unterdrücken

Die von dieser Annotation betroffenen Klassen, Methoden und Eigenschaften unterdrücken die Anzeige des Compilers Warnungen, seine Parameter dienen hauptsächlich für Warnanweisungen und Abbruch (nicht aktiviert) usw.

@SuppressWarnings("取消此类的所有警告")
public class BuiltAnnotation {
    
    @SuppressWarnings("取消此属性的警告")
    private String username;

    @SuppressWarnings("取消此方法的警告")
    public static void main(String[] args) {
        // ...
    }
}
Nach dem Login kopieren

1.3 Meta-Annotation

Die Rolle der Meta-Annotation besteht darin, andere Annotationen zu kommentieren. Java definiert 4 Standard-Meta-Annotationstypen, die Beschreibungen des Umfangs bereitstellen und Arten anderer Anmerkungen sowie andere Anmerkungen können durch Meta-Anmerkungen angepasst werden.

@Target: Beschreiben Sie den Anwendungsbereich von Anmerkungen. @Target(ElementType .TYPE) gibt an, dass es auf eine Klasse oder Schnittstelle usw. wirkt.

/**
 * @Target注解:描述注解的使用范围
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    /**
     * 类或接口:ElementType.TYPE;
     * 字段:ElementType.FIELD;
     * 方法:ElementType.METHOD;
     * 构造方法:ElementType.CONSTRUCTOR;
     * 方法参数:ElementType.PARAMETER;
     * ...
     */
    ElementType[] value();
}
Nach dem Login kopieren

@Retention: Gibt an, auf welcher Ebene die Anmerkungsinformationen gespeichert und zur Beschreibung verwendet werden müssen der Lebenszyklus der Annotation

#🎜 🎜#

Normalerweise verwenden benutzerdefinierte Annotationen @Retention(RetentionPolicy.RUNTIME), was den Laufzeiteffekt darstellt.

/**
 * @Retention:表示需要在什么级别保存该注解信息,用于描述注解的生命周期
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * RetentionPolicy.SOURCE:仅编译期,注解将被编译器丢弃。
     * RetentionPolicy.CLASS:仅class文件,注释将由编译器记录在类文件中,但VM不需要在运行时保留,如果不指定则默认为class。
     * RetentionPolicy.RUNTIME:运行期,注释将由编译器记录在类文件中,并由VM在运行时保留,因此可以反射读取。通常自定义的注解都是RUNTIME。
     * 范围:RUNTIME>CLASS>SOURCE
     */
    RetentionPolicy value();
}
Nach dem Login kopieren

@Document: Gibt an, dass dieser Hinweis in das Javadoc aufgenommen wird.

@Iherited: Definiert, ob Unterklassen vererbbar sind Von der übergeordneten Klasse definierte Anmerkungen.

@Inherited ist nur für Annotationen vom Typ @Target(ElementType.TYPE) nützlich und kann nur eine Vererbung der Klasse sein, keine Vererbung der Schnittstelle: 1.4 Benutzerdefinierte Anmerkung

Definitionsanmerkung

/**
 * 1. 使用@interface定义注解;
 * 3. 通过元注解配置该注解,配置注解的使用范围和生命周期等
 * @author Loner
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Report{
    /**
     * 2. 添加参数、默认值,如果没有默认值,就必须给参数赋值,一般把最常用的参数定义为value(),推荐所有参数都尽量设置默认值
     * 形式为:参数类型 参数名();
     */
    int type() default 0;
    String value() default "LonerMJ";
}
Nach dem Login kopieren

Anmerkung verwenden

@Report(type = 1, value = "test")
public class CustomerAnnotation {
    @Report(type = 1, value = "test")
    public void testCustomerAnnotation() {
        System.out.println("测试自定义注解");
    }
}
Nach dem Login kopieren
#🎜 🎜# 2. Reflexion

2.1 Reflexion und Reflexionsmechanismus

Reflexion

Reflexion (Reflexion) bezieht sich auf Das Programm kann alles erhalten Informationen über ein Objekt zur Laufzeit.

Reflexionsmechanismus

Der Reflexionsmechanismus bedeutet, dass das Programm, wenn es ausgeführt wird, die Inhaltsinformationen jeder Klasse über die Reflection-API erhält. und kann alle internen Eigenschaften und Methoden des Objekts direkt bedienen.

2.2 So erhalten Sie die Class-Klasse und allgemeine Methoden

java.lang.Class-Klasse, die Kernklasse, die die Reflektion nach Abschluss des Klassenladens in der Methode implementiert Bereich des Heap-Speichers Es wird ein Klassenobjekt generiert (eine Klasse hat nur ein Klassenobjekt). Durch dieses Objekt können Sie die Struktur der Klasse sehen.

So erhalten Sie die Klassenklasse

public class InstantiationClass {
    public static void main(String[] args) throws ClassNotFoundException {
        Teacher teacher = new Teacher("张三", "123456");

        // 方式一:调用Class类的静态方法forName(String className)
        Class<?> c1 = Class.forName("com.loner.mj.reflection.Teacher");

        // 方式二:已知某个类的实例,调用该实例的getClass()方法,getClass是Object类中的方法。
        Class<? extends Teacher> c2 = teacher.getClass();

        // 方式三:已知具体类,通过类的class属性获取,该方法最安全可靠,程序性能最高
        Class<Teacher> c3 = Teacher.class;

        // 方式四:通过基本内置类型的包装类的TYPE属性获得CLass实例
        Class<Integer> c4 = Integer.TYPE;

        // 方式五:通过当前子类的Class对象获得父类的Class对象
        Class<?> c5 = c1.getSuperclass();
    }
}
Nach dem Login kopieren

Gemeinsame Methoden der Klassenklasse#🎜🎜 #

Methodenname

MethodenfunktionDas Klassenobjekt des angegebenen Klassennamens zurückgeben Klassenobjekt Eine Instanz von String getName()Gibt die durch diese Klasse dargestellte Entität (Klasse, Schnittstelle, Array-Klasse oder Leere) zurück Objektname Klasse getSuperclass()Gibt das Klassenobjekt der übergeordneten Klasse des aktuellen Klassenobjekts zurück Class[] getinterfaces()Gibt die Schnittstelle des aktuellen Klassenobjekts zurückClassLoader getClassLoader( )# 🎜🎜#Gibt den Klassenlader dieser Klasse zurück Holen Sie sich die Methode, deren Methodenname mit der Parameterliste übereinstimmt. geerbte Methoden#🎜 🎜##🎜 🎜 #Alle Attribute abrufenField[] getFields()Constructor getConstructor(Class< ;?>... parameterTypesDie zur Parameterliste passende Konstruktormethode abrufen Konstruktor getConstructors()#🎜🎜 #Alle Konstruktoren der Klasse abrufen#🎜 🎜#Geben Sie die angegebene Annotation#🎜🎜 ## 🎜 🎜 ## 🎜🎜 ## 🎜🎜##Annotation [] getDeclaredAnnotations ()#🎜🎜 ## 🎜🎜#zurück alle Annotationen#🎜🎜 ## 🎜🎜 ## 🎜🎜 🎜🎜 🎜🎜#zurückgeben #
public class ReflectionMethods {
    public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException {
        Class<Worker> workerClass = Worker.class;

        /**
         * 类
         */
        System.out.println(workerClass.getName());
        System.out.println(workerClass.getSimpleName());
        System.out.println(workerClass.getSuperclass());
        System.out.println(workerClass.getPackage());
        Class<?>[] interfaces = workerClass.getInterfaces();
        for (Class<?> i : interfaces) {
            System.out.println(i);
        }

        /**
         * 属性
         */
        // 获取所有的属性
        Field[] declaredFields = workerClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        // 获取指定属性
        System.out.println(workerClass.getDeclaredField("username"));
        // 获取所有公共属性
        Field[] fields = workerClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }

        /**
         * 构造方法
         */
        // 获取所有构造方法
        Constructor<?>[] declaredConstructors = workerClass.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
        // 获取指定的构造方法
        System.out.println(workerClass.getDeclaredConstructor(String.class, String.class));

        /**
         * 方法
         */
        // 获取所有的方法
        Method[] declaredMethods = workerClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        // 获取指定方法
        System.out.println(workerClass.getDeclaredMethod("getUsername", null));
        // 获取所有功能方法
        Method[] methods = workerClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
    }
}
Nach dem Login kopieren

哪些类型具有Class对象

public class InstantiationClass {
    public static void main(String[] args) throws ClassNotFoundException {
        // 类(外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类。)
        Class<Object> objectClass = Object.class;
        // 接口
        Class<Comparable> comparableClass = Comparable.class;
        // 数组
        Class<String[]> stringClass = String[].class;
        Class<int[][]> intClass = int[][].class;
        // 枚举
        Class<ElementType> elementTypeClass = ElementType.class;
        // 注解
        Class<Override> overrideClass = Override.class;
        // 基本数据类型
        Class<Integer> integerClass = Integer.class;
        // void
        Class<Void> voidClass = void.class;
        // Class
        Class<Class> classClass = Class.class;
    }
}
Nach dem Login kopieren

2.3 反射的使用

反射操作对象

public class UseClass {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        Class<User> userClass = User.class;

        /**
         * 通过构造器实例化对象:不使用构造器,默认通过无参构造进行对象创建
         */
        Constructor<User> declaredConstructor = userClass.getDeclaredConstructor(String.class, String.class);
        User user = declaredConstructor.newInstance("张三", "123456");
        System.out.println(user);

        /**
         * 调用方法并执行相关操作
         */
        Method setUsername = userClass.getDeclaredMethod("setUsername", String.class);
        // invoke(Object, 参数):激活,即执行相关操作为该对象
        setUsername.invoke(user, "李四");
        Method setPassword = userClass.getDeclaredMethod("setPassword", String.class);
        setPassword.invoke(user, "123456");
        System.out.println(user);

        /**
         * 操作属性:通过反射直接操作私有属性会报错,需要通过setAccessible(ture)关闭访问安全检查,此方法属性、方法和构造都具有,会影响效率
         */
        Field username = userClass.getDeclaredField("username");
        username.setAccessible(true);
        username.set(user, "用户名");
        System.out.println(user);
    }
}
Nach dem Login kopieren

反射操作泛型

Java采用泛型擦除的机制来引入泛型,Java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换问题。但是,一旦编译完成,所有和泛型有关的类型全部擦除。

为了通过反射操作这些类型,Java新增了ParameterizedType,GenericArrayType,TypeVariable和WildcardType几种类型来代表不能被归一到Class类中的类型但是又和原始类型齐名的类型。

ParameterizedType:表示一种参数化类型,比如Collection

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

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

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

public class ClassOperateGenerics {
    public Map<String, String> list() {
        System.out.println("返回值是泛型");
        return new HashMap<>();
    }

    public void test(Map<String, User> map, List<Integer> list) {
        System.out.println("参数是泛型");
    }

    public static void main(String[] args) throws NoSuchMethodException {
        /**
         * 获取方法参数的泛型
         */
        Method method = ClassOperateGenerics.class.getMethod("test", Map.class, List.class);
        // 获取所有方法参数的泛型
        Type[] genericParameterTypes = method.getGenericParameterTypes();
        for (Type genericParameterType : genericParameterTypes) {
            // java.util.Map<java.lang.String, com.loner.mj.reflection.User>
            System.out.println(genericParameterType);
            if (genericParameterType instanceof ParameterizedType) {
                // 获取所有泛型的真实参数
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {
                    // String, User, Integer
                    System.out.println(actualTypeArgument);
                }
            }
        }

        /**
         * 获取方法返回值的泛型
         */
        Method list = ClassOperateGenerics.class.getMethod("list", null);
        // 获取方法返回值的泛型
        Type genericReturnType = list.getGenericReturnType();
        if (genericReturnType instanceof ParameterizedType) {
            // 获取所有泛型的真实参数
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println(actualTypeArgument);
            }
        }
    }
}
Nach dem Login kopieren

反射操作注解

public class ClassOperateAnnotation {
    public static void main(String[] args) throws NoSuchFieldException {
        Class<People> peopleClass = People.class;

        // 获取类的所有注解
        Annotation[] declaredAnnotations = peopleClass.getDeclaredAnnotations();
        for (Annotation declaredAnnotation : declaredAnnotations) {
            System.out.println(declaredAnnotation);
        }
        // 获取类的注解的值
        Table declaredAnnotation = peopleClass.getDeclaredAnnotation(Table.class);
        System.out.println(declaredAnnotation.value());

        // 获取属性的注解
        Field name = peopleClass.getDeclaredField("name");
        Fields annotation = name.getAnnotation(Fields.class);
        System.out.println(annotation.name());
    }
}
Nach dem Login kopieren

Das obige ist der detaillierte Inhalt vonSo verwenden Sie Anmerkungen und Reflexion in Java. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:yisu.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
statische Klasse forName(String name)#🎜 🎜#
#🎜🎜 ##🎜🎜 #
Methode getDeclareMethod(String name, Class ... parameterTypes)#🎜 🎜#
Method[] getMethods()Alle nicht privaten Methoden abrufen
Feld getDeclareField(String name )Spezifizierte Attribute abrufen
Field[] getDeclareFields()# 🎜🎜#
Alle nicht-privaten Eigenschaften abrufen#🎜 🎜#
A getAnnotation(Class annotationClass)