java——反射与注解(上)

简介: java——反射与注解

Java反射基础


了解Java反射的概念和原理,熟悉Class、Method、Field等反射API的使用方法,能够通过反射来动态地创建对象、调用方法、设置字段等。

Java反射是Java语言中非常重要的一个特性,它允许程序在运行时获取类的信息,并且可以通过反射调用类的方法、读写类的属性等。下面是Java反射基础概念和示例代码:


1. 概念详解

Java反射的核心是Class类,它代表了一个Java类的类型信息。通过Class可以获取到类的各种信息,例如类的名称、字段、方法、构造方法等。


获取Class对象的三种方式:


使用对象.getClass()方法获取对象的Class对象。

通过类名.class来获取指定类的Class对象。

使用Class.forName(“类名”)方法获取指定类的Class对象。


2. 示例代码


以下是一个简单的Java反射示例,它演示了如何通过反射创建对象、调用方法和设置字段:


public class Person {
    private String name;
    private int age;
    public Person() {}
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void sayHello() {
        System.out.println("Hello, I'm " + name + ", " + age + " years old.");
    }
}
public class ReflectionDemo {
    public static void main(String[] args) throws Exception {
        // 创建Person类的Class对象
        Class<Person> clazz = Person.class;
        // 创建Person类的实例
        Person person = clazz.newInstance();
        // 获取Person类的name字段,并设置其值
        Field nameField = clazz.getDeclaredField("name");
        nameField.setAccessible(true);
        nameField.set(person, "Tom");
        // 获取Person类的age字段,并设置其值
        Field ageField = clazz.getDeclaredField("age");
        ageField.setAccessible(true);
        ageField.setInt(person, 18);
        // 调用Person类的sayHello方法
        Method sayHelloMethod = clazz.getDeclaredMethod("sayHello");
        sayHelloMethod.invoke(person); // 输出:Hello, I'm Tom, 18 years old.
    }
}


在上面的示例代码中,通过Class对象获取了Person类的信息,然后使用newInstance()方法创建一个Person类的实例。接着,通过反射获取到Person类的name和age字段,并分别为它们设置了值。最后,通过反射获取到Person类的sayHello方法,并调用该方法输出一句话。


Java反射进阶


深入学习Java反射的应用场景,例如框架设计、动态代理、模板方法等;掌握Java反射中常用的技巧和注意事项,提高反射编程的效率和可维护性。

Java反射是指在运行时动态地获取一个类的信息,对类的属性和方法进行操作。它可以让我们在运行时通过字符串来调用类的方法或创建对象,而不需要提前知道该类的名称。Java反射广泛应用于框架设计、动态代理、模板方法等场景。


下面分别介绍Java反射在框架设计、动态代理、模板方法等场景中的应用,并给出常用技巧和注意事项。


1. 框架设计


在框架设计中,Java反射被广泛应用于插件机制和配置文件解析等场景。例如,Spring框架就使用了Java反射来实现依赖注入和AOP等功能。


常用技巧:


1)获取Class对象:使用Class.forName()或Object.getClass()方法获取Class对象。


2)创建对象:使用Class.newInstance()方法或Constructor.newInstance()方法创建对象。


3)调用方法:使用Method.invoke()方法调用方法。


4)读取字段:使用Field.get()方法读取字段的值。


5)修改字段:使用Field.set()方法修改字段的值。


注意事项:


1)性能问题:Java反射的性能较低,因为它需要在运行时进行类型检查和方法调用。


2)安全问题:Java反射可以访问私有成员和方法,因此可能会破坏封装性和安全性。


示例代码:

public class ReflectTest {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("com.example.User");
        Object obj = clazz.newInstance();
        Method setNameMethod = clazz.getMethod("setName", String.class);
        setNameMethod.invoke(obj, "Alice");
        Method getNameMethod = clazz.getMethod("getName");
        String name = (String) getNameMethod.invoke(obj);
        System.out.println(name);
        Field ageField = clazz.getDeclaredField("age");
        ageField.setAccessible(true);
        ageField.set(obj, 18);
        int age = (int) ageField.get(obj);
        System.out.println(age);
    }
}

2. 动态代理


在动态代理中,Java反射被用来动态地生成代理类。代理类可以拦截目标方法的调用并进行增强或修改。


常用技巧:


1)代理类的生成:使用Proxy.newProxyInstance()方法生成代理类。


2)InvocationHandler接口的实现:通过实现InvocationHandler接口来拦截目标方法的调用并进行处理。


注意事项:


1)代理类必须实现至少一个接口。


2)动态代理只能代理接口类型的对象,无法代理普通类。


示例代码:

public interface IUserDao {
    void save();
}
public class UserDaoImpl implements IUserDao {
    @Override
    public void save() {
        System.out.println("Save user...");
    }
}
public class UserDaoProxy implements InvocationHandler {
    private Object target;
    public UserDaoProxy(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Begin transaction...");
        Object result = method.invoke(target, args);
        System.out.println("Commit transaction...");
        return result;
    }
}
public class ProxyTest {
    public static void main(String[] args) {
        IUserDao userDao = new UserDaoImpl();
        InvocationHandler handler = new UserDaoProxy(userDao);
        IUserDao proxy = (IUserDao) Proxy.newProxyInstance(
            userDao.getClass().getClassLoader(),
            userDao.getClass().getInterfaces(),
            handler);
        proxy.save(); // Begin transaction...Save user...Commit transaction...
    }
}


3. 模板方法


在模板方法中,Java反射被用来实现框架的扩展性。通过Java反射,我们可以动态地调用扩展类中的方法,并将其与框架中的标准方法组合起来形成一个完整的流程。


常用技巧:


1)获取方法:使用Class.getDeclaredMethod()或Class.getMethod()方法获取方法。


2)设置方法可访问性:使用Method.setAccessible()方法将方法设为可访问。


3)调用方法:使用Method.invoke()方法调用方法。


注意事项:


1)扩展类必须实现一个标准的接口或继承一个标准的抽象类,以便框架能够调用扩展类中的方法。


2)需要确保扩展类中的方法与框架中的标准方法具有相同的名称和参数列表。


示例代码:

public interface ITemplate {
    void execute();
}
public abstract class AbstractTemplate implements ITemplate {
    @Override
    public final void execute() {
        init();
        doTask();
        destroy();
    }
    protected void init() {
        System.out.println("Initialize template...");
    }
    protected abstract void doTask();
    protected void destroy() {
        System.out.println("Destroy template...");
    }
}
public class MyTemplate extends AbstractTemplate {
    @Override
    protected void doTask() {
        System.out.println("Do my task...");
    }
}
public class TemplateTest {
    public static void main(String[] args) throws Exception {
        ITemplate template = new MyTemplate();
        Method method = template.getClass().getMethod("doTask");
        method.setAccessible(true);
        method.invoke(template); // Do my task...
    }
}


以上是Java反射在框架设计、动态代理和模板方法等场景中的应用,常用技巧和注意事项。希望可以帮助您深入学习Java反射。


Java注解基础


了解Java注解的概念和基本语法,学习如何自定义注解,并且通过反射来获取注解信息。

Java注解是一种元数据,它可以在代码中以声明的形式出现,但不直接参与编译和执行。Java注解可以用来提供程序中所需的任何基本信息,例如作者、版本、版权等。Java注解广泛应用于框架设计、测试驱动开发、配置文件解析等场景。


下面介绍Java注解的概念、基本语法和自定义注解,并通过反射来获取注解信息。


1. 概念


Java注解(Annotation)是一种附加在代码中的修饰符,用于在源代码中嵌入元数据。Java注解可以用来提供程序中所需的任何基本信息,例如作者、版本、版权等。Java注解可以在编译时通过工具进行处理,或者在运行时由Java虚拟机进行处理。


2. 基本语法


Java注解的基本语法如下:

@AnnotationName
public class MyClass {
    // ...
}


其中,@AnnotationName是注解的名称,它可以在代码中的类、方法、字段或参数上使用。注解可以带有元素,元素以名字-值对的形式存在,用逗号分隔多个元素。例如:

@AnnotationName(name = "Alice", age = 18)
public class MyClass {
    // ...
}


3. 自定义注解


我们可以通过Java的元注解来自定义注解。Java的元注解包括@Retention、@Target、@Inherited和@Documented。其中,@Retention用于指定注解的生命周期,@Target用于指定注解可以应用于哪些元素,@Inherited用于指定子类是否继承注解,@Documented用于指定注解是否出现在Java文档中。


示例代码:

import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
    String name();
    int age() default 18;
}


上述代码定义了一个名为MyAnnotation的注解,它有两个属性:name和age。其中,@Retention(RetentionPolicy.RUNTIME)表示该注解可以在运行时保留,@Target(ElementType.TYPE)表示该注解只能应用于类。


4. 反射获取注解信息


我们可以使用Java反射来获取注解信息。通过Class对象的getAnnotation()方法或Method对象的getAnnotation()方法可以获取指定注解的实例。然后,我们可以通过访问注解的属性来获取信息。


示例代码:

@MyAnnotation(name = "Alice", age = 18)
public class MyClass {
    // ...
}
public class ReflectTest {
    public static void main(String[] args) {
        Class<?> clazz = MyClass.class;
        MyAnnotation annotation = clazz.getAnnotation(MyAnnotation.class);
        if (annotation != null) {
            System.out.println(annotation.name()); // Alice
            System.out.println(annotation.age()); // 18
        }
    }
}
相关文章
|
23天前
|
XML Java 编译器
Java学习十六—掌握注解:让编程更简单
Java 注解(Annotation)是一种特殊的语法结构,可以在代码中嵌入元数据。它们不直接影响代码的运行,但可以通过工具和框架提供额外的信息,帮助在编译、部署或运行时进行处理。
86 43
Java学习十六—掌握注解:让编程更简单
|
18天前
|
Java 开发者 Spring
[Java]自定义注解
本文介绍了Java中的四个元注解(@Target、@Retention、@Documented、@Inherited)及其使用方法,并详细讲解了自定义注解的定义和使用细节。文章还提到了Spring框架中的@AliasFor注解,通过示例帮助读者更好地理解和应用这些注解。文中强调了注解的生命周期、继承性和文档化特性,适合初学者和进阶开发者参考。
40 14
|
18天前
|
前端开发 Java
[Java]讲解@CallerSensitive注解
本文介绍了 `@CallerSensitive` 注解及其作用,通过 `Reflection.getCallerClass()` 方法返回调用方的 Class 对象。文章还详细解释了如何通过配置 VM Options 使自定义类被启动类加载器加载,以识别该注解。涉及的 VM Options 包括 `-Xbootclasspath`、`-Xbootclasspath/a` 和 `-Xbootclasspath/p`。最后,推荐了几篇关于 ClassLoader 的详细文章,供读者进一步学习。
27 12
|
20天前
|
存储 Java
[Java]反射
本文详细介绍了Java反射机制的基本概念、使用方法及其注意事项。首先解释了反射的定义和类加载过程,接着通过具体示例展示了如何使用反射获取和操作类的构造方法、方法和变量。文章还讨论了反射在类加载、内部类、父类成员访问等方面的特殊行为,并提供了通过反射跳过泛型检查的示例。最后,简要介绍了字面量和符号引用的概念。全文旨在帮助读者深入理解反射机制及其应用场景。
13 0
[Java]反射
|
2月前
|
安全 Java 索引
Java——反射&枚举
本文介绍了Java反射机制及其应用,包括获取Class对象、构造方法、成员变量和成员方法。反射允许在运行时动态操作类和对象,例如创建对象、调用方法和访问字段。文章详细解释了不同方法的使用方式及其注意事项,并展示了如何通过反射获取类的各种信息。此外,还介绍了枚举类型的特点和使用方法,包括枚举的构造方法及其在反射中的特殊处理。
62 9
Java——反射&枚举
|
1月前
|
安全 Java 测试技术
🌟Java零基础-反射:从入门到精通
【10月更文挑战第4天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
25 2
|
11天前
|
Java 编译器
Java进阶之标准注解
Java进阶之标准注解
24 0
|
2月前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
|
1月前
|
JSON Java 数据库
java 常用注解大全、注解笔记
关于Java常用注解的大全和笔记,涵盖了实体类、JSON处理、HTTP请求映射等多个方面的注解使用。
34 0
java 常用注解大全、注解笔记
|
29天前
|
IDE Java 编译器
java的反射与注解
java的反射与注解
16 0