java反射和注解

1.反射与Class类

  • Java本是静态语言,但反射提供了动态语言的特性,通过反射可以获得任意类的所有结构,并可以任意操作类内部的属性和方法

  • 类加载完毕后,堆空间中会出现唯一的Class对象,这个对象clazz包含了该类的所有结构

  • Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass 方法自动构造的

  • 通过反射的方式获取对象效率远远不如直接new,当且仅当不能直接new对象的时候用反射创建对象,在主流框架中大量使用了反射
    普通方法即直接new

2.Class对象获取

一个类的Class对象无论用什么方式获取多少次,都是唯一的

new 目标类().getClass()

  • 不建议这样使用,已经可以直接new了就不要再反射获取对象了

  • new Student()的同时也会在堆空间产生全局唯一的Student类对象

    Student stu1 = new Student();//这一new 产生一个Student对象,一个Class对象。
    Class stuClass = stu1.getClass();//获取Class对象
    System.out.println(stuClass.getName());

目标类.class;

这种方法也不推荐,需要额外在调用处导入目标类的包,依赖过强

	//第二种方式获取Class对象
	Class stuClass2 = Student.class;

forName()方法——最常用

一般都第三种,一个字符串可以传入也可写在配置文件中等多种方法。

	//第三种方式获取Class对象
	try {
		Class stuClass3 = Class.forName("com.fanshe.Student");//全类名路径
	} catch (ClassNotFoundException e) {
		e.printStackTrace();
	}

基本数据类型和包装类

包装类.TYPE属性 相当于 基本数据类型.class属性

    Class<Integer> c1 = int.class;
    Class<Integer> c2 = Integer.TYPE;
    System.out.println(c1==c2);//true

源码
@SuppressWarnings(“unchecked”)
public static final Class TYPE = (Class) Class.getPrimitiveClass(“int”);

3.Class类常用方法

3.1静态方法

获取目标类的Class对象

3.2非静态方法

对于:Class c1 = Class.forName(“com.zjh.User”);

获取目标类实例

c1.newInstance()

获取目标类全类名路径

c1,getName()

获取父类的Class对象

c1.getSuperClass().getSuperClass()....可以一直链路向上调用

获取类的方法Method对象,invoke激活

不加Declared的getMethods()包括父类的方法

先获取Method对象(无参可以不填or填null),然后invoke调用方法

    Class c1 = Class.forName("filter.User");
    
    Method tell = c1.getMethod("tell", String.class);
    Object content = tell.invoke(new User(), "说话内容");
    System.out.println(content);//null无返回值

获取类的构造器

没有形参的就是获取所有,注意是否为s结尾复数,形参列表是Class对象; 没有Declared的就是只获取public修饰的

  • 批量的方法:返回数组
    public Constructor[] getConstructors():所有"公有的"构造方法
    public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
  • 单个的方法,并调用:
    public Constructor getConstructor(**Class… parameterTypes **):获取单个的"公有的"构造方法:
    public Constructor getDeclaredConstructor(Class… parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;

调用时使用使用newInstance()

    Class c1 = Class.forName("filter.User");

    Constructor constructor = c1.getConstructor(String.class, int.class);
    Object u = constructor.newInstance("牛逼", 12);
    System.out.println(u);

获取类的属性

没有形参的就是获取所有,注意是否为s结尾复数,形参是String类型即指定获取某属性; 没有Declared的就是只获取public修饰的

  • 批量的:
    Field[] getFields():获取所有的"公有属性",包括父类
    Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
  • 获取单个的:
    public Field getField(String fieldName):获取某个"公有的"字段;
    public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)

————————————————————————————————————

如果使用getField(“name”)会由于私有属性抛java.lang.NoSuchFieldException: name

如果使用 Field name =c1.getDeclaredField(“name”);但是如果不 name.setAccessible(true); 就会抛异常
java.lang.IllegalAccessException

获取类的加载器

类的加载器分为:

c1.getClassLoader()

4.反射获取注解信息

4.1自定义注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyValue {
    //给字段赋值
    String value();
}


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyTable {
    //表名
    String value();
}



@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface MyController {
    //URL
    String value();
}


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyColumn {
    //字段名绑定
    String value();
}

4.2待绑定的Bean

@MyTable("table_people")
public class PeopleBean {

    @MyValue("zjh")
    @MyColumn("xx_name")
    private String name;

    @MyValue("18")
    @MyColumn("xx_age")
    private int age;

    @Override
    public String toString() {
        return "PeopleBean{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

4.3测试

@MyController("/com/baidu/www")
public class MyTest {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {

        //1.获取当前URL
        Class<MyTest> c1 = MyTest.class;
        MyController anno1 = c1.getAnnotation(MyController.class);
        String value1 = anno1.value();
        System.out.println("当前URL是:" + value1);


        //2.反射获取PeopleBean,并用@value对其赋值
        Class c2 = Class.forName("filter.PeopleBean");
        PeopleBean people= (PeopleBean)c2.newInstance();

        //3.PeopleBean直接获取的注解只有@MyTable
        Annotation[] annotations = c2.getDeclaredAnnotations();
        System.out.println("类级别的注解数:"+annotations.length);//1

        //4.获取类中所有不包括父类的属性
        Field[] fields = c2.getDeclaredFields();
        for (Field f : fields) {
            //@MyColumn绑定的字段信息
            MyColumn column = f.getDeclaredAnnotation(MyColumn.class);
            System.out.println(f.getName() + "绑定的表字段是:" + column.value());

            //@MyValue赋值操作
            MyValue Myvalue = f.getAnnotation(MyValue.class);
            String toValue = Myvalue.value();

            f.setAccessible(true);
            //对@MyValue目标绑定数据类型进行判断并赋值
            if(f.getType().getName().equals("int")){//判断属性是否是int类型
                f.set(people, Integer.parseInt(toValue));
            }else{
                f.set(people, toValue);
            }
        }

        System.out.println(people);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值