反射,注解

本文深入探讨了Java反射机制的应用,包括如何使用反射获取类的信息、创建对象、调用方法及修改属性值。通过一个具体的Person类示例,展示了反射在实际编程中的强大功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//注解
@UserInfo(userName = "枫叶",userPassword = "123456")
public class Person {
    public String nikeName="枫叶";
    public String name;

    private String age;
    private String idNum;
    public Person() {

    }

    public Person(String name) {
        this.name = name;
    }

    public Person(String nikeName, String name) {
        this.nikeName = nikeName;
        this.name = name;
    }

    private Person(String nikeName, String name,String age){
        this.nikeName = nikeName;
        this.name = name;
        this.age=age;
    }
    public void eat(){
        Log.d("nikeName",nikeName + "吃饭");
    }
    public void sleep(){
        Log.d("nikeName",nikeName + "睡觉");
    }
    public void hit(int count){
        Log.d("nikeName",nikeName + "走路"+count+"次");
    }
}

//注解接口

@Retention(RetentionPolicy.RUNTIME)
public @interface UserInfo {
    String userName();
    String userPassword();
}
public class Test {

    private Context context;

    public Test(Context context) {
        this.context = context;
    }

    public void testReflect() throws Exception {
        //获取class对象
        Class<Person> personClass = Person.class;
        Class aClass = new Person().getClass();
        //要使用类的全路径名
        Class person = Class.forName("com.bw.fengye.marquee.Person");

        //获取所用公共(public)属性
        Field[] fields = personClass.getFields();
        //获取单个属性
        Field nikeName = personClass.getField("nikeName");

        //获取所用属性(所有声明的属性)
        Field[] declaredFields = personClass.getDeclaredFields();
        Field idNum = personClass.getDeclaredField("idNum");

        //获取无参构造方法东方不败
        Constructor[] constructors = personClass.getConstructors();
        Constructor[] declaredConstructors = personClass.getDeclaredConstructors();

        //获取有参构造方法
        Constructor declaredConstructor = personClass.getDeclaredConstructor(String.class);
        Constructor declaredConstructor1 = personClass.getDeclaredConstructor(String.class, String.class);
        Constructor<Person> declaredConstructor2 = personClass.getDeclaredConstructor(String.class, String.class, String.class);

        //通过实例化对象
        Person person1 = personClass.newInstance();
        Person o = (Person) declaredConstructor1.newInstance("林青霞", "东方不败");

        //获取所有公共方法
        Method[] methods = personClass.getMethods();
        //获取所有的方法
        Method[] declaredMethods = personClass.getDeclaredMethods();

        //获取单个public方法
        Method eat = personClass.getMethod("eat");
        Method hit = personClass.getMethod("hit", int.class);

        //获取单个私有方法
        Method sleep = personClass.getDeclaredMethod("sleep");

        //调用方法
        eat.invoke(person1);
        eat.invoke(o);
        hit.invoke(person1,10);
        hit.invoke(o,100);

        //更改public属性值
        nikeName.set(o,"王祖贤");
        idNum.setAccessible(true);
        idNum.set(o,"18");


        Class<Person> personClass1 = Person.class;
        UserInfo annotation = personClass1.getAnnotation(UserInfo.class);
        String name = annotation.userName();
        String password = annotation.userPassword();
        if(name.equals("枫叶")){
            Toast.makeText(context,"名号没错",Toast.LENGTH_SHORT).show();
            if(password.equals("123456")){
                Toast.makeText(context,"密码没错",Toast.LENGTH_SHORT).show();
            }
        }else {
            Toast.makeText(context,"有错",Toast.LENGTH_SHORT).show();
        }

    }
}

//单机之后调用Test()方法

public class MainActivity extends AppCompatActivity {

    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.textView);
        textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Person person=new Person();
                person.eat();
                person.sleep();
                person.hit(5);
                Test test=new Test(MainActivity.this);
                try {
                    test.testReflect();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

}
<think>我们有一个用户查询,要求了解Java反射注解的使用方法或实现原理。用户特别提到了“使用教程”或“实现原理”,因此我们的回答需要覆盖这两方面。根据提供的引用,我们可以总结出以下关键点:1.引用[1]提到反射的方式:实例化对象、通过getClass方法、得到包等。但文本不完整,我们可以参考其他引用。2.引用[2]强调注解在日常开发中使用多,反射较少,但框架底层大量使用。同时提到注解反射是基本功,面试常问。3.引用[3]的目录结构提供了注解反射的详细大纲:包括注解的概念、内置注解、元注解、自定义注解反射的概念、动态语言与静态语言、Java反射机制、反射API、Class类、类加载过程、类加载器、运行时类的结构、泛型信息以及操作注解。4.引用[4]提到“反射操作注解”,这也是一个重要的应用。因此,我们组织回答的结构如下:1.先简要介绍反射注解的概念及其重要性。2.分别讲解反射的使用方法和原理。-反射的使用:包括获取Class对象的三种方式、通过反射获取构造方法并创建对象、获取字段和方法、调用方法等。-反射的原理:涉及JVM的类加载机制、Class对象、方法区等。3.然后讲解注解的使用方法和原理。-注解的使用:内置注解(如@Override)、元注解(如@Target)、自定义注解注解的解析(反射或编译时处理)。-注解的原理:注解本质上是接口,而注解信息的存储和读取由JVM实现。4.最后,结合反射注解:如何通过反射获取注解信息并利用。注意:使用教程部分需要代码示例,而原理部分需要解释机制。由于用户要求使用中文,我们使用中文回答。另外,我们还需要生成相关问题。下面开始编写回答。</think> ### Java反射注解的使用与原理 #### **一、反射的使用方法** 1. **核心API** - **获取Class对象**(三种方式): ```java Class<?> clazz1 = Class.forName("java.lang.String"); // 类全路径 Class<?> clazz2 = String.class; // 类字面量 Class<?> clazz3 = "".getClass(); // 对象.getClass() ``` - **操作类成员**: ```java // 获取构造方法并实例化 Constructor<?> cons = clazz1.getConstructor(String.class); Object obj = cons.newInstance("Hello"); // 调用方法 Method method = clazz1.getMethod("length"); int length = (int) method.invoke(obj); // 返回字符串长度 // 访问字段 Field field = clazz1.getDeclaredField("value"); field.setAccessible(true); // 打破私有限制 char[] chars = (char[]) field.get(obj); ``` 2. **应用场景** - 动态加载类(如插件化开发) - 框架底层(如Spring的IoC容器通过反射创建Bean) - 调试工具(查看运行时对象结构) --- #### **二、注解的使用方法** 1. **内置常用注解** | 注解 | 作用 | |---------------|-------------------------------| | `@Override` | 标记方法重写父类/接口方法 | | `@Deprecated` | 标记已过时方法/类 | | `@SuppressWarnings` | 抑制编译器警告 | 2. **自定义注解** ```java @Target(ElementType.METHOD) // 仅用于方法 @Retention(RetentionPolicy.RUNTIME) // 运行时保留 public @interface MyAnnotation { String value() default ""; // 带默认值的属性 int priority() default 0; } ``` - `@Target`:定义注解作用目标(类、方法、字段等) - `@Retention`:定义注解生命周期(源码、编译、运行时) 3. **注解解析(结合反射)** ```java Method method = obj.getClass().getMethod("myMethod"); if (method.isAnnotationPresent(MyAnnotation.class)) { MyAnnotation anno = method.getAnnotation(MyAnnotation.class); System.out.println("Priority: " + anno.priority()); } ``` --- #### **三、反射注解的实现原理** 1. **反射原理** - JVM在类加载时生成`Class`对象(位于方法区) - Class对象包含类元数据:字段、方法、构造器等指针 - 反射调用本质是通过`Class`对象访问这些元数据 - **性能开销**:绕过了编译器优化,需安全检查(可通过`setAccessible(true)`减少开销)[^3] 2. **注解原理** - 注解本质是继承`Annotation`的接口 - 编译器为注解生成代理类(如`$Proxy1`) - 运行时通过动态代理解析注解属性 - 注解信息存储在类文件的`RuntimeVisibleAnnotations`属性中 3. **关键内存结构** ```mermaid graph LR A[Java源文件] --编译--> B[字节码文件] B --类加载--> C[方法区] C --> D[Class对象] D --> E[字段/方法/构造器指针] D --> F[注解存储区] ``` --- #### **四、反射操作注解的典型应用** 1. **ORM框架映射** ```java @Table("user") // 自定义注解 public class User { @Column("id") private int userId; public static void main(String[] args) { Table tableAnno = User.class.getAnnotation(Table.class); String tableName = tableAnno.value(); // 获取表名"user" // 通过反射读取字段注解生成SQL } } ``` 2. **注解处理器** - **编译时处理**(如Lombok):继承`AbstractProcessor`修改AST - **运行时处理**:结合反射动态改变行为(如权限检查) --- ### 相关问题 1. 为什么反射会降低性能?有哪些优化反射调用的方法? 2. 如何在编译时处理注解(如Lombok原理)? 3. 如何利用注解实现简单的AOP功能(如权限校验)? 4. `@Retention(RetentionPolicy.SOURCE)`和`RUNTIME`的应用场景有什么区别? [^1]: Java注解反射的核心机制 [^2]: 框架对反射注解的依赖场景 [^3]: JVM类加载与反射的底层交互过程 [^4]: 反射注解在实际工程中的取舍
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值