反射和注解

反射和注解

反射

“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”,如Python,Ruby是动态语言;显然C++,Java,C#不是动态语言,但是JAVA有着一个非常突出的动态相关机制:Reflection

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制,很多优秀的开源框架都是通过反射完成的。

功能

java反射机制可以实现以下功能:

①在运行时判断任意一个对象所属的类;
②在运行时构造任意一个类的对象;
③在运行时判断任意一个类所具有的成员变量和方法;
④在运行时调用任意一个对象的方法;
⑤生成动态代理

了解反射首先需要获取源头Class

所有的类其实都是Class的实例。这个Class实例可以理解为类的模子,通过其来创建各种类。

获取Class对象三种方式

第一种方式:类.class

        // 1、通过类.class获取Class对象
        Class c = String.class;
        System.out.println(c);

		//输出
        class java.lang.String

第二种方式:对象.getClass()

        // 2、通过对象.getClass()方法获取Class对象
        String s = "";
        System.out.println(s.getClass());

		//输出
        class java.lang.String

第三种方式:Class.forName

        // 3、通过class.forName("包名.类名")-->推荐使用
        Class c2 = Class.forName("java.lang.String");
        System.out.println(c2);

		//输出
        class java.lang.String

这里介绍一个方法,通过获取Class对象获取父类的class对象

        // 4、通过Class对象获取父类的Class对象
        Class<?> superclass = "".getClass().getSuperclass();
        System.out.println(superclass);

		//输出
		class java.lang.Object

修饰符

通过getModifiers()方法获取修饰符, Modifier类提供了 static 方法和常量来解码类和成员访问修饰符

下面是对应的修饰符的常量表示表格:

get.Modifiers()返回的是修复符的常量和
public --> return 1
public final --> return 16+1
  • Modifier and TypeConstant FieldValue
    public static final intABSTRACT1024
    public static final intFINAL16
    public static final intINTERFACE512
    public static final intNATIVE256
    public static final intPRIVATE2
    public static final intPROTECTED4
    public static final intPUBLIC1
    public static final intSTATIC8
    public static final intSTRICT2048
    public static final intSYNCHRONIZED32
    public static final intTRANSIENT128
    public static final intVOLATILE64

反射创建对象

根据Class对象, 我们可以获取某个类的构造器,进而创建类的对象。

代码演示:

// 这里的User是一个User类,使用的是泛型,传入的是User.class对象

public static void newClass(Class<User> cls) throws Exception {
        // 1、newInstance()自动调用无参构造器创建对象
        User u1 = cls.newInstance();
        System.out.println(u1);

        // 2、Constructor() 通过构造器获取对象
        //   1)getConstructor(Class<?> ... paramType)可变参数选择不同参数的构造器获取
    	// 获取User类的无参构造器
        Constructor<User> con1 = cls.getConstructor();
        System.out.println(con1);
    	// 获取无参构造器之后通过newInstance()创建对象
 	    System.out.println(con1.newInstance());	

    	// 获取User的 private User(Integer id)一个参数的构造器
        Constructor<User> con2 = cls.getDeclaredConstructor(Integer.class);
        System.out.println(con2);
        // 调用私有权限构造器方法需要调用setAccessible()方法,忽略权限,true为开启,false为关闭
        con2.setAccessible(true);
        System.out.println(con2.newInstance(1000));
        con2.setAccessible(false);
		// 获取User的双参构造器
        Constructor<User> con3 = cls.getConstructor(String.class, String.class);
        System.out.println(con3);
    	System.out.println(con3.newInstance("张三","123"));
    }

反射操作方法

具体 的方法查看API文档,

Package java.lang.reflect

提供用于获取关于类和对象的反射信息的类和接口。

演示一些常用方法:

public static void getMethodTest(Class<User> cls) throws Exception{
        // 所有的方法
        // getMethods()返回所有方法,包含父类继承
        // getDeclaredMethods()返回所有方法,只有自己内部的方法
        Method[] methods = cls.getDeclaredMethods();
        for (Method m : methods) {
            System.out.println(m);
        }

        // 获取指定的公共的方法,使用Method类接收
        Method methodGet = cls.getMethod("getPwd");
        // 创建对象调用方法
        User user = cls.getConstructor(Integer.class,String.class,String.class).newInstance(1200,"李四","123123");
        // 获取方法
        Method methodSet = cls.getDeclaredMethod("setPwd", String.class);

        // 调用setPwd方法
        methodSet.invoke(user, "123456");
        // 调用getPwd方法,使用获取到的Method对象调用 Invoke(调用对象,对应的方法参数)方法 
        String s = (String) methodGet.invoke(user);
        System.out.println(s);

        // 私有方法
        // 方法忽略权限问题
        methods[4].setAccessible(true);
        methods[4].invoke(user);

        // 静态方法
        Method hello = cls.getDeclaredMethod("hello");
        System.out.println(hello);
        hello.invoke(user);
    }

反射操作属性

在这里演示一些简单方法操作属性,具体的请阅读相关API文档。

public static void testField(Class<User> cls) throws Exception {
        // 创建对象调用方法
        User user = cls.getConstructor(Integer.class,String.class,String.class).newInstance(1200,"李四","123123");
        // 获取属性,getField()、getDeclaredField()都可以
        Field name = cls.getDeclaredField("name");
        // 开启权限忽略
        name.setAccessible(true);
        // 修改属性,set(调用对象,方法参数)
        name.set(user, "王五");
        // 获取属性值
        System.out.println(name.get(user));
        // 获取name属性的修饰符对应的常量值
        System.out.println(name.getModifiers());
        // 获取修饰符
        System.out.println(Modifier.toString(name.getModifiers()));
    }

注解

注解是Java 1.5 引入的,目前已被广泛应用于各种Java框架,如Hibernate,Jersey、Spring。注解相当于是一种嵌入在程序中的 元数据 ,可以使用注解解析工具或编译器对其进行解析,也可以指定注解在编译期或运行期有效。在注解诞生之前,程序的元数据存在的形式仅限于java注释或javadoc,但注解可以提供更多功能,它不仅包含元数据,还能作用于运行期,注解解析器能够使用注解决定处理流程。

Annotation(注解)就是Java提供了一种元程序中的元素关联任何信息和任何元数据 (metadata)的途径和方法。Annotation是一个接口,程序可以通过反射来获取指定程序元素的Annotation对象,然后通过Annotation对象来获取注解里面的元数据。注解API非常强大,被广泛应用于各种Java框架

元数据:描述数据的数据

注解的分类

根据注解参数的个数分类

1)、标记注解:一个没有成员定义的Annotation类型被称为标记注解。

2)、单值注解:只有一个值

3)、完整注解:拥有多个值

根据注解使用方法和用途分类

1)、JDK内置系统注解

2)、元注解

3)、自定义注解

内置注解

@Override

限定重写父类方法,若想要重写父类的一个方法时,需要使用该注解告知编译器我们正在重写一个方法。如此一来,当父类的方法被删除或修改了,编译器会提示错误信息;或者该方法不是重写也会提示错误。

public class User{
    public void eat(){
        System.out.println("吃饭");
    }
}
// 重写在一定程度上体现了多态现象
class Student extends User{
    @Override
    public void eat(){
        System.out.println("学生正在吃饭");
    }
}

@Deprecated

标记已过时,当我们想要让编译器知道一个方法已经被弃用(deprecate)时,应该使用这个注解。Java推荐在javadoc中提供信息,告知用户为什么这个方法被弃用了,以及替代方法是什么

/**
* Deprecated -->该方法过时(有更好的解决方案)
*/
public class TestDeprecated {
  @Deprecated
  public int test(){
  
 System.out.println("TestDeprecated.test()");
    return 0;
 }
  public void test(int a){
  
 System.out.println("TestDeprecated.test(int)"
);
 }
}

@SuppressWarnings

抑制编译器警告,该注解仅仅告知编译器,忽略它们产生了特殊警告。如:在java泛型中使用原始类型。其保持性策略(retention policy)是SOURCE,在编译器中将被丢弃。

/**
* SuppressWarnings 压制警告,更多的请去官网查询
* @author Administrator
*/
public class TestSuppressWarnings {
  public static void main(String[] args) {
    @SuppressWarnings("unused")// 没有使用的代码
    List<String> list =new
ArrayList<String>();
 }
  @SuppressWarnings("rawtypes") //没有定义范型
  public static List test(){
    return new ArrayList();
 }
}

自定义注解

// @Target标记自定义注解使用的范围,方法、属性、类等等
@Target(ElementType.METHOD)
// @Retention标记自定义注解的生命周期,源码SOURCE、编译CLASS、运行RUNTIME
@Retention(RetentionPolicy.RUNTIME)
public @interface Identify {
// 一个属性的时候建议使用value()
    int value();
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值