广告
返回顶部
首页 > 资讯 > 后端开发 > Python >java中反射和注解的简单使用方法
  • 756
分享到

java中反射和注解的简单使用方法

2024-04-02 19:04:59 756人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

目录什么反射?Java反射机制提供的功能反射相关的主要apiClass 类获取Class 类的实例( 四种方法)哪些类型可以有Class 对象?演示Class类的常用方法有了Clas

什么反射?

Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。

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

Java反射机制提供的功能

  1. 在运行时判断任意一个对象所属的类
  2. 在运行时构造任意一个类的对象
  3. 在运行时判断任意一个类所具有的成员变量和方法
  4. 在运行时获取泛型信息
  5. 在运行时调用任意一个对象的成员变量和方法
  6. 在运行时处理注解
  7. 生成动态代理

反射相关的主要API

java.lang.Class: 代表一 个 类

java.lang.reflect.Method: 代表类 的 方法

java.lang.reflect.Field: 代表类的 成员 变量

java.lang.reflect.Constructor: 代表类 的 构造

Class 类

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

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

Class类的常用方法

方法名 功能说明
static Class forName(String name)  返回指定类名 name 的 Class 对象
Object newInstance() 调用缺省构造函数,返回该Class对象的一个实例
getName() 返回此Class对象所表示的实体(类、接口、数组类、基本类型
或void)名称
Class getSuperClass()  返回当前Class对象的父类的Class对象
Class [] getInterfaces()  获取当前Class对象的接口
ClassLoader getClassLoader()  返回该类的类加载器
Class getSuperclass() 返回表示此Class所表示的实体的超类的Class
Constructor[] getConstructors()  返回一个包含某些Constructor对象的数组
Field[] getDeclaredFields()  返回Field对象的一个数组
Method getMethod(String
name,Class … paramTypes)
返回一个Method对象,此对象的形参类型为paramType

获取Class 类的实例( 四种方法)

先创建一个实体类


package com.chen.pojo;
 
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
 
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Car {
    public String brand="宝马";
    public int price=500000;
    public String color="白色";
 
}

1.前提:已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取,可能抛出 ClassNotFoundException


  //1.Class.forName,应用场景:多用于配置文件,读取类全路径,加载类
        String classAllPath="com.chen.pojo.Car";
        Class<?> cls1=Class.forName(classAllPath);

输出结果:

2.前提:若已知具体的类,通过类的class属性获取,该方法最为安全可靠,程序性能最高


 
        //2.类名.class,应用场景:用于参数传递
        Class<Car> cls2 = Car.class;
        System.out.println(cls2);

 输出结果:

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


/3.对象.getClass(),应用场景,有对象实例
        Car car=new Car();
        Class cls3=car.getClass();
        System.out.println(cls3);

输出结果:

4.其他方式(不做要求)


   //4.通过类加载器(4)种来获取类的Class对象
        //(1)先得到类加载器car
        ClassLoader classLoader=car.getClass().getClassLoader();
        //(2)通过类加载器得到Class对象
        Class<?> cls4=classLoader.loadClass(classAllPath);
        System.out.println(cls4);

 //cls1,cls2,cls3,cls4 其实是同一个对象
        System.out.println(cls1.hashCode());
        System.out.println(cls2.hashCode());
        System.out.println(cls3.hashCode());
        System.out.println(cls4.hashCode());

//5. 基本数据(int,char,boolean,float,double,byte,long,short) 按如下方式得到Class类对象
        Class<Integer> integerClass=int.class;
        Class<Character> characterClass=char.class;
        Class<Boolean> booleanClass=boolean.class;
        System.out.println(integerClass);
 
        //6.基本数据类型对应的包装类,可以通过 .TYPE 得到class类对象
        Class<Integer> type1=Integer.TYPE;
        Class<Character> type2 = Character.TYPE;//其它包装类BOOLEAN,DOUBLE,LONG,BYTE
        System.out.println(type1);

哪些类型可以有Class 对象?

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

(2)interface:接口

(3)[]:数组

(4)enum:枚举

(5)annotation:注解@interface

(6)primitive type:基本数据类型

(7)void


        Class<String> cls1=String.class;//外部类
        Class<Serializable> cls2=Serializable.class;//接口
        Class<Integer[]> cls3 = Integer[].class;//数组
        Class<float[][]> cls4 = float[][].class;//二维数组
        Class<Deprecated> cls5 = Deprecated.class;//注解
        //枚举
        Class<Thread.State> cls6 = Thread.State.class;
        Class<Long> cls7 = long.class;
        Class<Void> cls8= void.class;
        Class<Class> cls9 = Class.class;
 
        System.out.println(cls1);
        System.out.println(cls2);
        System.out.println(cls3);
        System.out.println(cls4);
        System.out.println(cls5);
        System.out.println(cls6);
        System.out.println(cls7);
        System.out.println(cls8);
        System.out.println(cls9);

演示Class类的常用方法


package com.chen;
 
 
import com.chen.pojo.Car;
 
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
 
//演示Class类的常用方法
public class Class02 {
 
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
 
        String classAllPath="com.chen.pojo.Car";
        //1.获取Car类对应的Class对象
        //<?>表示不确定的Java类
        Class<?> cls=Class.forName(classAllPath);
        //2.输出cls
        System.out.println(cls);//显示cls对象,是哪个类的Class对象 class com.chen.pojo.Car
        System.out.println(cls.getClass());//输出cls运行类型 class java.lang.Class
 
        //3.得到包名
        System.out.println(cls.getPackage().getName());
 
        //4.得到全类名
        System.out.println(cls.getName());
 
        //5.通过cls创建对象实例
        Car car= (Car) cls.newInstance();
        System.out.println(car);
 
        //6.通过反射获取属性 brand
        Field brand=cls.getField("brand");
        System.out.println(brand.get(car));
 
        //7.通过反射给属性赋值
        brand.set(car,"奔驰");
        System.out.println(brand.get(car));
 
        //8.获取所有属性(字段)
        Field[] fields=cls.getFields();
        for (Field field:fields){
            System.out.println(field.getName());
        }
 
 
    }
 
}

输出结果

有了Class对象,能做什么?

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

Field 、Method 、Constructor 、Superclass 、Interface 、Annotation(实现的全部接口  所继承的父类  全部的构造器  全部的方法  全部的Field)

1. 实现的全部接口

public Class<?>[] getInterfaces()
确定此对象所表示的类或接口实现的接口。

2. 所继承的父类

public Class<? Super T> getSuperclass()
返回表示此 Class 所表示的实体(类、接口、基本类型)的父类的
Class。

3. 全部的构造器

public Constructor<T>[] getConstructors()
返回此 Class 对象所表示的类的所有public构造方法。
public Constructor<T>[] getDeclaredConstructors()
返回此 Class 对象表示的类声明的所有构造方法。
Constructor类中:
 取得修饰符: public int getModifiers();
取得方法名称: public String getName();
 取得参数的类型:public Class<?>[] getParameterTypes();

4. 全部的方法

 public Method[] getDeclaredMethods()
返回此Class对象所表示的类或接口的全部方法
 public Method[] getMethods()
返回此Class对象所表示的类或接口的public的方法
 Method类中:
 public Class<?> getReturnType()取得全部的返回值
 public Class<?>[] getParameterTypes()取得全部的参数
 public int getModifiers()取得修饰符
 public Class<?>[] getExceptionTypes()取得异常信息

 5. 全部的Field

public Field[] getFields()
返回此Class对象所表示的类或接口的public的Field。
public Field[] getDeclaredFields()
返回此Class对象所表示的类或接口的全部Field。
 Field方法中:
public int getModifiers() 以整数形式返回此Field的修饰符
 public Class<?> getType() 得到Field的属性类型
 public String getName() 返回Field的名称。

6. Annotation 相关

get Annotation(Class<T> annotationClass)
getDeclaredAnnotations() 

7. 泛型相关

获取父类泛型类型:Type getGenericSuperclass()
泛型类型:ParameterizedType
获取实际的泛型类型参数数组:getActualTypeArguments() 

 8. 类所在的包 Package getPackage()

例:


package com.chen;
 
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
 
//演示如来通过反射获取类的结构信息
public class ReflectionUtils {
 
 
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
      //api_o1();
        api_o2();
    }
 
    //第一组API
    public static void api_o1() throws ClassNotFoundException, NoSuchMethodException {
 
        //得到Class对象
        Class<?> person=Class.forName("com.chen.Person");
        //getName:获取全类名
        System.out.println(person.getName());
        //getSimpleName:获取简单类名
        System.out.println(person.getSimpleName());
        //getFields:获取所有public修饰的属性,包含本类以及父类的
        Field[] fields=person.getFields();
        for(Field field:fields){
            System.out.println("本类以及父类的属性="+field.getName());
        }
        //getDeclaredFields:获取本类中所有属性
        Field[] declaredFields = person.getDeclaredFields();
        for(Field declaredField:declaredFields){
            System.out.println("本类中所有属性="+declaredField.getName());
        }
        //getMethods:获取所有public修饰的方法,包含本类以及父类的
        Method[] methods=person.getMethods();
        for(Method method:methods){
            System.out.println("本类及父类的方法="+method.getName());
        }
        //getDeclaredMethods:获取本类中所有的方法
        Method[] declareMethods=person.getDeclaredMethods();
        for(Method declareMethod:declareMethods){
            System.out.println("本类中所有的方法:"+declareMethod);
        }
        //getConstructors:获取所有public修饰的构造器,包含本类
        Constructor<?>[] constructors = person.getConstructors();
        for(Constructor<?> constructor:constructors){
            System.out.println("本类的构造器="+constructor.getName());
        }
        //getDeclaredConstructors:获取本类中所有的构造器
         Constructor<?>[] declaredConstructors=person.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor:declaredConstructors){
            System.out.println("本类中所有的构造器="+declaredConstructor.getName());
            System.out.println("本类中所有的构造器="+declaredConstructor);
        }
        //getPackage:以Package形式返回 包信息
        System.out.println(person.getPackage());
        //getSuperClass:以Class形式返回父类信息
        Class<?> superclass = person.getSuperclass();
        System.out.println("以Class形式返回父类信息"+superclass);
        //getInterfaces:以Class[]形式返回接口信息
        Class<?>[] interfaces = person.getInterfaces();
       for (Class<?> aninterface:interfaces){
           System.out.println("接口信息"+aninterface);
        }
        //getAnnotat ions:以Annotation[]形式返回注解信息
        Annotation[] annotations=person.getAnnotations();
       for (Annotation annotation:annotations){
           System.out.println("注解信息="+annotation);
       }
 
 
 
    }
 
    public static void api_o2() throws ClassNotFoundException, NoSuchMethodException {
 
        //得到Class对象
        Class<?> person=Class.forName("com.chen.Person");
        //getDeclaredFields:获取本类中所有属性
        //规定说明:默认修饰符是0,public是1,private是2,protected是4,static是8,final是16,】  public(1)+static(8)=9
        Field[] declaredFields = person.getDeclaredFields();
        for(Field declaredField:declaredFields){
            System.out.println("本类中所有属性="+declaredField.getName()+"该属性的修饰符="+declaredField.getModifiers()
            +" 该属性的类型="+declaredField.getType());
        }
 
        //getDeclaredMethods:获取本类中所有的方法
        Method[] declareMethods=person.getDeclaredMethods();
        for(Method declareMethod:declareMethods){
            System.out.println("本类中所有的方法:"+declareMethod
            +" 该方法的访问修饰符="+declareMethod.getModifiers()
            +" 该方法返回类型="+declareMethod.getReturnType());
 
            //输出当前这个方法的形参数组情况
            Class<?>[] parameterTypes=declareMethod.getParameterTypes();
            for(Class<?> parameterType:parameterTypes){
                System.out.println("该方法的形参类型="+parameterType);
            }
 
        }
 
        //getDeclaredConstructors:获取本类中所有的构造器
        Constructor<?>[] declaredConstructors=person.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor:declaredConstructors){
            System.out.println("===============");
            System.out.println("本类中所有的构造器="+declaredConstructor.getName());
            System.out.println("本类中所有的构造器="+declaredConstructor);
 
            Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
            for(Class<?> parameterType:parameterTypes){
                System.out.println("该构造器的形参类型="+parameterType);
            }
 
        }
 
 
    }
 
}
 
interface IA{
 
}
 
interface IB{
 
}
 
 
class A {
    public String hobby;
    public void hi(){
 
    }
    public A() {
 
    }
}
 
@Deprecated
class Person extends A implements IA,IB{
 
    //属性
    public String name;
    protected int age;
    String job;
    private double sal;
 
    public Person(){
 
    }
 
    public Person(String name)
    {
 
    }
    private Person(String name,int age){
 
    }
 
    //方法
    public void m1(String name,int age,double sal){
 
    }
   private void m2(){
 
    }
   protected void m3(){
 
    }
   void m4(){
 
    }
    public void m5(){
 
    }
 
 
}

输出结果:

com.chen.Person
Person
本类以及父类的属性=name
本类以及父类的属性=hobby
本类中所有属性=name
本类中所有属性=age
本类中所有属性=job
本类中所有属性=sal
本类及父类的方法=m5
本类及父类的方法=m1
本类及父类的方法=hi
本类及父类的方法=wait
本类及父类的方法=wait
本类及父类的方法=wait
本类及父类的方法=equals
本类及父类的方法=toString
本类及父类的方法=hashCode
本类及父类的方法=getClass
本类及父类的方法=notify
本类及父类的方法=notifyAll
本类中所有的方法:public void com.chen.Person.m5()
本类中所有的方法:private void com.chen.Person.m2()
本类中所有的方法:void com.chen.Person.m4()
本类中所有的方法:public void com.chen.Person.m1(java.lang.String,int,double)
本类中所有的方法:protected void com.chen.Person.m3()
本类的构造器=com.chen.Person
本类的构造器=com.chen.Person
本类中所有的构造器=com.chen.Person
本类中所有的构造器=private com.chen.Person(java.lang.String,int)
本类中所有的构造器=com.chen.Person
本类中所有的构造器=public com.chen.Person(java.lang.String)
本类中所有的构造器=com.chen.Person
本类中所有的构造器=public com.chen.Person()
package com.chen
以Class形式返回父类信息class com.chen.A
接口信息interface com.chen.IA
接口信息interface com.chen.IB
注解信息=@java.lang.Deprecated()
本类中所有属性=name该属性的修饰符=1 该属性的类型=class java.lang.String
本类中所有属性=age该属性的修饰符=4 该属性的类型=int
本类中所有属性=job该属性的修饰符=0 该属性的类型=class java.lang.String
本类中所有属性=sal该属性的修饰符=2 该属性的类型=double
本类中所有的方法:public void com.chen.Person.m5() 该方法的访问修饰符=1 该方法返回类型=void
本类中所有的方法:private void com.chen.Person.m2() 该方法的访问修饰符=2 该方法返回类型=void
本类中所有的方法:void com.chen.Person.m4() 该方法的访问修饰符=0 该方法返回类型=void
本类中所有的方法:public void com.chen.Person.m1(java.lang.String,int,double) 该方法的访问修饰符=1 该方法返回类型=void
该方法的形参类型=class java.lang.String
该方法的形参类型=int
该方法的形参类型=double
本类中所有的方法:protected void com.chen.Person.m3() 该方法的访问修饰符=4 该方法返回类型=void
===============
本类中所有的构造器=com.chen.Person
本类中所有的构造器=private com.chen.Person(java.lang.String,int)
该构造器的形参类型=class java.lang.String
该构造器的形参类型=int
===============
本类中所有的构造器=com.chen.Person
本类中所有的构造器=public com.chen.Person(java.lang.String)
该构造器的形参类型=class java.lang.String
===============
本类中所有的构造器=com.chen.Person
本类中所有的构造器=public com.chen.Person()

调用运行时类的指定结构

1. 调用指定方法

通过反射,调用类中的方法,通过Method类完成。步骤:

1.通过Class类的getMethod(String name,Class…parameterTypes)方法取得一个Method对象,并设置此方法操作时所需要的参数类型。

2.之后使用Object invoke(Object obj, Object[] args)进行调用,并向方法中传递要设置的obj对象的参数信息。

Object invoke(Object obj, Object … args说明:
1.Object 对应原方法的返回值,若原方法无返回值,此时返回null
2.若原方法若为静态方法,此时形参Object obj可为null
3.若原方法形参列表为空,则Object[] args为null
4.若原方法声明为private,则需要在调用此invoke()方法前,显式调用方法对象的setAccessible(true)方法,将可访问private的方法

 例:


package com.chen;
 
//演示通过反射调用方法
 
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
 
public class ReflecAcceSSMethod {
 
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
 
 
        //1.得到Boss 类对应的class对象
        Class<?> boossCls=Class.forName("com.chen.Boss");
        //2.创建对象
        Object o=boossCls.newInstance();
        //3调用public的hi方法
        Method hi=boossCls.getMethod("hi",String.class);
        //3.1得到hi方法对象
        Method hi2=boossCls.getDeclaredMethod("hi",String.class);
         hi.invoke(o,"hhhh");
         hi2.invoke(o,"hhhh2");
 
         //4.调用private static 方法
        //4.1得到say方法对象
        Method say=boossCls.getDeclaredMethod("say", int.class, String.class, char.class);
        //4.2因为say方法private,所以需要爆破,原理和前面讲的构造器和属性一样
        say.setAccessible(true);
        System.out.println(say.invoke(o,100,"栈说",'男'));
        //4.3因为say方法是static,还可以这样用,可以传入null
        System.out.println(say.invoke(null,200,"栈说2",'男'));
 
        //5.在反射中,如果方法有返回值,统一返回Object,但是他运行类型和方法定义的返回值类型一致
        Object invoke = say.invoke(null, 300, "小明", '男');
        System.out.println("reVal的运行类型="+invoke);
    }
 
}
 
class Boss{//类
 
    public int age;
    private static String name;
 
    public Boss(){
 
    }
 
    private static String say(int n,String s,char c){
        return n+" "+s+" " +c;
    }
 
    public void hi(String s){
        System.out.println("hi "+s);
    }
}

运行结果:

hi hhhh
hi hhhh2
100 栈说 男
200 栈说2 男
reVal的运行类型=300 小明 男

2.调用指定属性

在反射机制中,可以直接通过Field类操作类中的属性,通过Field类提供的set()和get()方法就可以完成设置和取得属性内容的操作。

 public Field getField(String name) 返回此Class对象表示的类或接口的指定的public的Field。
 public Field getDeclaredField(String name)返回此Class对象表示的类或接口的指定的Field。

在 在Field 中:

 public Object get(Object obj) 取得指定对象obj上此Field的属性内容
 public void set(Object obj,Object value) 设置指定对象obj上此Field的属性内容

例:


package com.chen;
 
 
import java.lang.reflect.Field;
 
//演示反射操作属性
public class RefleAccessProperty {
 
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
 
        //1.得到Student类对应的class对象
        Class<?> stuClass=Class.forName("com.chen.Student");
        //2.创建对象
        Object o=stuClass.newInstance();//o的运行类型就是student
        System.out.println(o.getClass());
        //3.使用反射得到age属性
        Field age = stuClass.getField("age");
        age.set(o,22);
        System.out.println(o);
        System.out.println(age.get(o));
 
        //4.使用反射操作name属性
        Field name = stuClass.getDeclaredField("name");
        //对name进行爆破
        name.setAccessible(true);
        name.set(o,"小黑");
        System.out.println(o);
        System.out.println(name.get(o));
 
 
    }
 
}
 
class Student{//类
 
    public int age=20;
    private static String name;
 
    public Student(){
 
    }
 
    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +  "  name=" + name +
                '}';
    }
}

输出结果:

class com.chen.Student
Student{age=22  name=null}
22
Student{age=22  name=小黑}
小黑

 关于setAccessible

Method和Field、Constructor对象都有setAccessible()方法。
 setAccessible启动和禁用访问安全检查的开关。
参数值为true则指示反射的对象在使用时应该取消Java语言访问检查。
提高反射的效率。如果代码中必须用反射,而该句代码需要频繁的被调用,那么请设置为true。
 使得原本无法访问的私有成员也可以访问
参数值为false则指示反射的对象应该实施Java语言访问检查

调用Class对象的newInstance()方法

1)类必须有一个无参数的构造器。
2)类的构造器的访问权限需要足够。

例:


package com.chen;
 
 
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
 
//演示通过反射机制创建实例
public class ReflecCreateInstance {
 
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        //1.先获取User类
        Class<?> userClass = Class.forName("com.chen.User");
 
        //2.通过public的无参构造器创建实例
        Object o = userClass.newInstance();
        System.out.println(o);
 
        //3.通过public的参数构造器创建实例
        
        Constructor<?> constructor = userClass.getConstructor(String.class);
        Object hh = constructor.newInstance("hh");
        System.out.println("hh="+hh);
        //4.通过非public的有参构造器创建实例
        //4.1先得到private的构造器对象
        Constructor<?> constructor1 = userClass.getDeclaredConstructor(int.class, String.class);
        //4.2 创建实例
        constructor1.setAccessible(true);//爆破,所有反射可以访问private构造器
        Object user2=constructor1.newInstance(100,"小明");
        System.out.println("user2="+user2);
 
    }
 
 
 
}
 
class User{
 
    private int age=10;
    private String name="hello";
    public User(){
 
 
    }
    public User(String name){
 
     this.name=name;
 
    }
    private User(int age,String name){
        this.age=age;
        this.name=name;
    }
 
    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

输出结果:

User{age=10, name='hello'}
hh=User{age=10, name='hh'}
user2=User{age=100, name='小明'}

综合案例:

例1:


package com.chen;
 
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
 
public class HomeWork01 {
 
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
        
 
        //1.得到PrivateTest类对应的class对象
        Class<PrivateTest> privateTestClass = PrivateTest.class;
        //2.创建对象实例
        PrivateTest privateTest = privateTestClass.newInstance();
        //3.得到name属性对象
        Field name = privateTestClass.getDeclaredField("name");
        //4.爆破name
        name.setAccessible(true);
        name.set(privateTest,"天龙八部");
        //5.得到getName方法对象
        Method getName = privateTestClass.getMethod("getName");
        Object invoke = getName.invoke(privateTest);
        System.out.println("name属性值"+invoke);
 
    }
 
}
 
class PrivateTest{
    private String name="hellokitty";
    public String getName(){
        return name;
    }
}

例2


package com.chen;
 
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
 
public class HomeWork02 {
 
 
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        
        //1.class类的forName方法得到File类的class对象
        Class<?> fileClass = Class.forName("java.io.File");
        //2.得到所有的构造器
        Constructor<?>[] declaredConstructors = fileClass.getDeclaredConstructors();
        //遍历输出
        for (Constructor<?> declaredConstructor:declaredConstructors){
            System.out.println("file构造器="+declaredConstructor);
        }
        //3.指定的得到public java.io.File(java.lang.String)
        Constructor<?> declaredConstructor = fileClass.getDeclaredConstructor(String.class);
        String fileAllPath="D:\\mynew.txt";
        Object file=declaredConstructor.newInstance(fileAllPath);
        //4.得到createNewFile的方法对象
        Method createNewFile = fileClass.getMethod("createNewFile");
        createNewFile.invoke(file);
        //file的运行类型就是File
        System.out.println(file.getClass());
        System.out.println("创建文件成功"+fileAllPath);
    }
}

输出结果:

file构造器=public java.io.File(java.lang.String,java.lang.String)
file构造器=public java.io.File(java.lang.String)
file构造器=private java.io.File(java.lang.String,java.io.File)
file构造器=public java.io.File(java.io.File,java.lang.String)
file构造器=public java.io.File(java.net.URI)
file构造器=private java.io.File(java.lang.String,int)
class java.io.File
创建文件成功D:\mynew.txt

注解

什么是注解?

从 JDK 5.0 开始, Java 增加了对元数据(MetaData) 的支持, 也就是Annotation(注解)
Annotation 其实就是代码里的 特殊标记, 这些标记可以在编译, 类加载, 运行时被读取, 并执行相应的处理。通过使用Annotation, 程序员可以在不改变原有逻辑的情况下, 在源文件中嵌入一些补充信息。代码分析工具开发工具和部署工具可以通过这些补充信息进行验证或者进行部署。
Annotation 可以像修饰符一样被使用, 可用于 修饰包, 类, 构造器, 方 方法 法, 成员变量, 参数, 局部变量的声明, 这些信息被保存在 Annotation的“name=value” 对中

 注解是一种趋势,一定程度上可以说:框架 = 注解 + 反射 + 设计模式。

常见的Annotation

示例一:生成文档相关的注解

@author 标明开发该类模块的作者,多个作者之间使用,分割
@version 标明该类模块的版本
@see 参考转向,也就是相关主题
@since 从哪个版本开始增加的
@param 对方法中某参数的说明,如果没有参数就不能写
@return 对方法返回值的说明,如果方法的返回值类型是void就不能写
@exception 对方法可能抛出的异常进行说明 ,如果方法没有用throws显式抛出的异常就不能写
其中
@param @return 和 @exception 这三个标记都是只用于方法的。
@param的格式要求:@param 形参名 形参类型 形参说明
@return 的格式要求:@return 返回值类型 返回值说明
@exception的格式要求:@exception 异常类型 异常说明
@param和@exception可以并列多个

例:



public class JavadocTest {

public static void main(String[] args) {
}

public static double getArea(double radius){
return Math.PI * radius * radius;
}
}

 示例二: 在编译时进行格式查 检查(JDK 内置的三个基本注解

@Override: 限定重写父类方法, 该注解只能用于方法
@Deprecated: 用于表示所修饰的元素(类, 方法等)已过时。通常是因为所修饰的结构危险或存在更好的选择
@SuppressWarnings: 抑制编译器警告

例:


public class AnnotationTest{
public static void main(String[] args) {
@SuppressWarnings("unused")
int a = 10;
}
@Deprecated
public void print(){
System.out.println("过时的方法");
}
@Override
public String toString() {
return "重写的toString方法()";
}
}

 示例三: 跟踪 代码依赖性,实现替代配置文件功能

@WEBServlet("/login")
public class LoginServlet extends httpservlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException { }
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
doGet(request, response);
} }

 JDK 中的元注解

JDK 的元 Annotation 用于修饰其他 Annotation 定义
JDK5.0提供了4个标准的meta-annotation类型,分别是:

RetentionTargetDocumentedInherited

1. Retention

@Retention: 只能用于修饰一个 Annotation 定义, 用于指定该 Annotation 的生命周期, @Rentention 包含一个 RetentionPolicy 类型的成员变量, 使用
@Rentention 时必须为该 value 成员变量指定值:
ØRetentionPolicy.SOURCE:在源文件中有效(即源文件保留),编译器直接丢弃这种策略的注释
ØRetentionPolicy.CLASS:在class文件中有效(即class保留) , 当运行 Java 程序时, JVM不会保留注解。 这是默认值
ØRetentionPolicy.RUNTIME:在运行时有效(即运行时保留),当 当行 运行 Java 程序时, JVM 会 会保留注释。程序 可以通过反射获取 该注释。 

 2. Target

用于修饰 Annotation 定义, 用于指定被修饰的 Annotation 能用于修饰哪些程序元素。 @Target 也包含一个名为 value 的成员变量。

 

 3. Documented

@Documented: 用于指定被该元 Annotation 修饰的 Annotation 类将被javadoc 工具提取成文档。默认情况下,javadoc是不包括注解的。
Ø定义为Documented的注解必须设置Retention值为RUNTIME。

4. Inherited

@Inherited: 被它修饰的 Annotation 将具有 继承性。如果某个类使用了被
@Inherited 修饰的 Annotation, 则其子类将自动具有该注解。
Ø比如:如果把标有@Inherited注解的自定义的注解标注在类级别上,子类则可以继承父类类级别的注解
Ø实际应用中,使用较少

自定义 Annotation

定义新的 Annotation 类型使用 @interface 关键字
l 自定义注解自动继承了java.lang.annotation.Annotation 接口
l Annotation 的成员变量在 Annotation 定义中以无参数方法的形式来声明。其方法名和返回值定义了该成员的名字和类型。我们称为配置参数。类型只能
是八种基本数据类型、String 类型 、Class 类型 、enum 类型 、Annotation 类型 、以上所有类型的 数组。
l 可以在定义 Annotation 的成员变量时为其指定初始值, 指定成员变量的初始值可使用 default 关键字
l 如果只有一个参数成员,建议使用 参数名为value
l 如果定义的注解含有配置参数,那么使用时必须指定参数值,除非它有默认值。格式是“参数名 = 参数值”,如果只有一个参数成员,且名称为value,可以省略“value=”
l 没有成员定义的 Annotation 称为 标记; 包含成员变量的 Annotation 称为元数据 Annotation
注意:自定义注解必须配上注解的信息处理流程才有意义。

例:


package com.chen.annotation;
 
import java.lang.annotation.*;
 
//自定义注解
@MyAnnotation2(id=1,name = "s")
public class MyAnnotation {
   //注解可以显示,默认值,如果没有默认值,我们就必须给注解赋值
   @MyAnnotation2(id=2,name = "小白",age=21,schools ={"中山大学" } )
    public void test(){
 
    }
    @MyAnnotation3("小黑")
    public void test2(){
 
    }
}
 
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface  MyAnnotation2{
 
    //注解的参数:参数类型+参数名();
  String name()   default  "";
  int age()  default 0;
  int id() ;
  String[] schools() default {"清华大学","北京大学"};
 
}
 
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface  MyAnnotation3{
 
    //注解的参数:参数类型+参数名();
    String value() ;
 
 
}

最后通过反射获取注解信息:


package com.chen.annotation;
 
import java.lang.annotation.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
 
//注解和反射
public class AnnotationAndReflect {
 
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class<?> aClass = Class.forName("com.chen.annotation.Student");
 
        //通过反射获得注解
        Annotation[] annotations = aClass.getAnnotations();
        for(Annotation annotation:annotations){
            System.out.println(annotation);
        }
 
        //获得注解的value的值
        TableStudent  tableAnnotation = aClass.getAnnotation(TableStudent.class);
        String value = tableAnnotation.value();
        System.out.println(value);
 
        //获得类指定的注解
        Field f= aClass.getDeclaredField("name");
        FieldStudent annotation = f.getAnnotation(FieldStudent.class);
        System.out.println(annotation.columnName());
        System.out.println(annotation.type());
        System.out.println(annotation.length());
 
        System.out.println("---------------");
        Field f2= aClass.getDeclaredField("age");
        FieldStudent annotation2 = f2.getAnnotation(FieldStudent.class);
        System.out.println(annotation2.columnName());
        System.out.println(annotation2.type());
        System.out.println(annotation2.length());
 
        System.out.println("---------------");
        Field f3= aClass.getDeclaredField("id");
        FieldStudent annotation3 = f3.getAnnotation(FieldStudent.class);
        System.out.println(annotation3.columnName());
        System.out.println(annotation3.type());
        System.out.println(annotation3.length());
 
    }
 
 
}
@TableStudent("db_student")
class Student{
    @FieldStudent(columnName = "db_id",type = "int",length = 10)
    private int id;
    @FieldStudent(columnName = "db_age",type = "int",length = 10)
    private int age;
    @FieldStudent(columnName = "db_name",type = "varchar",length = 5)
    private String name;
 
    public Student() {
 
    }
 
    public Student(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }
 
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}
 
//类名的注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface TableStudent{
    String value();
}
 
//属性的注解
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@interface FieldStudent{
    String columnName();
    String type();
    int length();
}

输出结果

@com.chen.annotation.TableStudent(value=db_student)
db_student
db_name
varchar
5
---------------
db_age
int
10
---------------
db_id
int
10

总结

到此这篇关于java中反射和注解的简单使用方法的文章就介绍到这了,更多相关java反射和注解使用内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: java中反射和注解的简单使用方法

本文链接: https://www.lsjlt.com/news/131726.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • java中反射和注解的简单使用方法
    目录什么反射?Java反射机制提供的功能反射相关的主要APIClass 类获取Class 类的实例( 四种方法)哪些类型可以有Class 对象?演示Class类的常用方法有了Clas...
    99+
    2022-11-12
  • 简单易懂Java反射的setAccessible()方法
    目录概要一、 什么是Java的访问检查二、 setAccessible() 方法介绍前言:在使用Field类的对象访问我自定义的Employee类对象的name域时,抛出异常ille...
    99+
    2022-11-13
  • java 中反射简单使用示例
    这篇文章将为大家详细讲解有关java 中反射简单使用示例,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。package reflect_test;public class Do...
    99+
    2023-06-02
  • Java中的注解和反射怎么使用
    这篇文章主要讲解了“Java中的注解和反射怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java中的注解和反射怎么使用”吧!1、注解(Annotation)1.1 什么是注解(Ann...
    99+
    2023-07-02
  • JAVA基础之注解与反射的使用方法和场景
    目录注解注解定义使用场景内置注解 元注解反射加载配置文件反射获取Class反射获取 Constructor反射获取 Method反射获取 Field通过反射获取注解信息内省...
    99+
    2022-11-11
  • java注解和反射怎么使用
    Java注解和反射是Java编程中非常重要的概念。注解是一种元数据,可以用来为Java程序提供额外的信息,而反射则允许程序在运行时动...
    99+
    2023-05-29
    java注解和反射 java
  • Java的反射(reflection)机制的简单使用
    目录 一、定义 二、用途 三、反射基本信息 四、反射相关的类 五、反射示例 六、反射的优点和缺点 一、定义         Java的反射机制是运行时的状态,可以通过反射来调用类里面的属性和方法,私有的属性和方法也可以调用,也可以对它...
    99+
    2023-10-27
    1024程序员节 java
  • Java利用自定义注解、反射实现简单BaseDao实例
    在常见的ORM框架中,大都提供了使用注解方式来实现entity与数据库的映射,这里简单地使用自定义注解与反射来生成可执行的sql语句。这是整体的目录结构,本来是为复习注解建立的项目^.^好的,首先我们来确定思路。1. 自定义@Table @...
    99+
    2023-05-31
    java 自定义注解 反射
  • Java通过反射注解赋值的方法详解
    目录问题描述最终解决if/else 普通解法通过反射注解赋值属性解题思路汇总某些字段的和总结源码前段时间,领导分配一个统计销售区域汇总的数据,解决方案使用到了反射获取注解,通过注解获...
    99+
    2022-11-13
  • java高级用法之注解和反射讲义
    前言 反射和注解在java中偏高级用法,一般在各种框架中被广泛应用,文章简单介绍下反射和注解的用法,希望对你的工作学习有一定帮助 java注解 什么是注解 Java 注解也就是An...
    99+
    2022-11-12
  • 如何在Java项目中使用注解和反射
    今天就跟大家聊聊有关如何在Java项目中使用注解和反射,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Java可以用来干什么Java主要应用于:1. web开发;2. Android开...
    99+
    2023-06-06
  • 一文搞懂Java中的注解和反射
    目录1、注解(Annotation)1.1 什么是注解(Annotation)1.2 内置注解1.3 元注解(meta-annotation)1.4 自定义注解2、反射(Reflec...
    99+
    2022-11-13
  • java反射调用方法NoSuchMethodException的解决方案
    目录java反射调用方法NoSuchMethodExceptionNoSuchMethodException问题总结1、编译异常,这个很容易发现并解决2、编译正常,运行报错java反...
    99+
    2022-11-13
  • Java反射的定义和用法详解
    目录定义获取Class对象1.1 通过类名获取Class对象1.2 通过对象获取Class对象1.3 通过类字面常量获取Class对象获取类的信息2.1 获取所有字段2.2 获取指定...
    99+
    2023-05-18
    Java反射 Java反射操作
  • Java反射的setAccessible()方法怎么使用
    本篇内容介绍了“Java反射的setAccessible()方法怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、 什么是Java的...
    99+
    2023-07-02
  • 深入解析Java中反射中的invoke()方法
    先讲一下java中的反射: 反射就是将类别的各个组成部分进行剖析,可以得到每个组成部分,就可以对每一部分进行操作 反射机制应用场景:逆向代码、动态生成类框架等,使用反射机制能够大大的...
    99+
    2022-11-12
  • 如何使用Java注解和反射实现Junit4中的用例调用
    这篇文章主要讲解了“如何使用Java注解和反射实现Junit4中的用例调用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何使用Java注解和反射实现Junit4中的用例调用”吧!实例需求需...
    99+
    2023-06-15
  • 怎么在java中使用反射调用方法
    这篇文章将为大家详细讲解有关怎么在java中使用反射调用方法,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。Java可以用来干什么Java主要应用于:1. web开发;2. Android开发...
    99+
    2023-06-14
  • 如何在java中使用反射调用方法
    这篇文章将为大家详细讲解有关如何在java中使用反射调用方法,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。Java有哪些集合类Java中的集合主要分为四类:1、List列表:有序的,可重复的...
    99+
    2023-06-14
  • 简单了解Java方法的定义和使用实现
    目录什么是方法?方法的定义2021.6.2 方法的重载(重要笔试可能遇到)命令行传参2021.6.3可变参数(也叫不定项参数)递归(重要,不推荐使用)2021.6.5什么是数组数组声...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作