Java注解与反射

本文探讨了Java反射机制的基础概念,包括类加载器的工作原理,如何通过Class对象获取构造器、方法、字段,以及注解的使用和获取。同时,详细讲解了内置注解如@Override和@Deprecated的用法,以及元注解如@Retention、@Documented和@Target的应用示例。
摘要由CSDN通过智能技术生成

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言


提示:以下是本篇文章正文内容,下面案例可供参考

一、注解

1. 内置注解

		@Override : 重写 *
		定义在java.lang.Override
		@Deprecated:废弃 *
		定义在java.lang.Deprecated
		SuppressWarnings:抑制编译时的警告信息。 *
		定义在java.lang.SuppressWarning
		三种使用方式
			1. @SuppressWarnings("unchecked") [^ 抑制单类型的警告]
			2. @SuppressWarnings("unchecked","rawtypes") [^ 抑制多类型的警告]
			3. @SuppressWarnings("all") [^ 抑制所有类型的警告]

2. 元注解

		介绍:作用在其他注解的注解,通俗来讲就是给注解类上再填上注解
		元注解:
				1.@Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可
				以通过反射访问。
				2.@Documented - 标记这些注解是否包含在用户文档中 javadoc。
				3.@Target - 标记这个注解应该是哪种 Java 成员,可以放在类的哪一个部分。
				4.@Inherited - 标记这个注解是自动继承的
		
	@Documented//注解是否包含在文档中
	//用途类型:该注解可以用在类型,方法上,字段上
	@Target(ElementType.FIELD)
	保存策略:RUNTIME该注解保存在源码,class文件和JVM中
	@Retention(RetentionPolicy.RUNTIME)
	该注解可以继承
	@Inherited
	public @interface ColumnAnnotation {
    String columnName();
    String type();
    String length();
}

二、Java反射机制

1.概述

JAVA反射机制是在运行状态中,获取任意一个类的结构 , 创建对象 , 得到方法,执行方法 , 属性 !;
这种在运行状态动态获取信息以及动态调用对象方法的功能被称为java语言的反射机制。

2.类加载器

		java默认有三种类加载器,BootstrapClassLoader、ExtensionClassLoader、App
		ClassLoader。
		BootstrapClassLoader(引导启动类加载器):
		嵌在JVM内核中的加载器,该加载器是用C++语言写的,主要负载加载JAVA_HOME/lib下的类库,引
		导启动类加载器无法被应用程序直接使用。
		ExtensionClassLoader(扩展类加载器):
		ExtensionClassLoader是用JAVA编写,且它的父类加载器是Bootstrap。
		是由sun.misc.Launcher$ExtClassLoader实现的,主要加载JAVA_HOME/lib/ext目录中的类
		库。
		它的父加载器是BootstrapClassLoader
		App ClassLoader(应用类加载器):
		App ClassLoader是应用程序类加载器,负责加载应用程序classpath目录下的所有jar和class文
		件。它的父加载器为Ext ClassLoader
		
		BootstrapClassLoader(引导启动类加载器)>ExtensionClassLoader(扩展类加载器)>App ClassLoader(应用类加载器)

在这里插入图片描述

		双亲委派模型:如果一个类加载器收到了一个类加载请求,它不会自己去尝试加载这个类,而是把这个请求
		转交给父类加载器去完成。每一个层次的类加载器都是如此。因此所有的类加载请求都应该传递到最顶层的
		启动类加载器中,只有到父类加载器反馈自己无法完成这个加载请求(在它的搜索范围没有找到这个类)
		时,子类加载器才会尝试自己去加载。委派的好处就是避免有些类被重复加载。
		ClassLoader classLoader = Demo3.class.getClassLoader();//获取当前类的加载器
        System.out.println(classLoader);

3.所有类的Class对象

		要想了解一个类,必须先要获取到该类的字节码文件对象.
		在Java中,每一个字节码文件,被夹在到内存后,都存在一个对应的Class类型的对象
		通俗来说,也就是 类的类型

4.得到Class的几种方式

		1. 如果在编写代码时, 指导类的名称, 且类已经存在, 可以通过
		包名.类名.class 得到一个类的 类对象
		2. 如果拥有类的对象, 可以通过
		Class 对象.getClass() 得到一个类的 类对象
		3. 如果在编写代码时, 知道类的名称 , 可以通过
		Class.forName(包名+类名): 得到一个类的 类对象

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

5.反射中拿到构造器

		1. 通过指定的参数类型, 获取指定的单个构造方法
		getConstructor(参数类型的class对象数组)
		例如:
		构造方法如下: Person(String name,int age)
		得到这个构造方法的代码如下:
		Constructor c = p.getClass().getConstructor(String.class,int.class);
		2. 获取构造方法数组
		getConstructors();
		3. 获取所有权限的单个构造方法
		getDeclaredConstructor(参数类型的class对象数组)
		4. 获取所有权限的构造方法数组
		getDeclaredConstructors();
		5.newInstance(Object... para)
		调用这个构造方法, 把对应的对象创建出来
		参数: 是一个Object类型可变参数, 传递的参数顺序 必须匹配构造方法中形式参数列表的顺
		序!
		6.setAccessible(boolean flag)
		如果flag为true 则表示忽略访问权限检查 !(可以访问任何权限的方法)
		public static void main(String[] args)throws Exception {
        //通过Class.forName拿到 person2的对象
        Class<Person2> p2 = (Class<Person2>) Class.forName("Person2");
        //获取p2的无参构造器
        Constructor<Person2> constructor = p2.getConstructor();
        //创建Person2的实例对象
        Person2 person2 = constructor.newInstance();
        //打印输出
        System.out.println(person2);

        //通过Class.forName拿到 person2的对象
        Class<Person2> p3 = (Class<Person2>) Class.forName("Person2");
        //获取包含String name和int age的p3的有参构造器
        Constructor<Person2> constructor3 = p3.getConstructor(String.class,int.class);
        //创建p3的实例对象
        Person2 person3 = constructor3.newInstance("张三",18);
        //打印输出
        System.out.println(person3);
    }

6.反射拿到方法

		1. getMethod(String methodName , class.. clss)
		根据参数列表的类型和方法名, 得到一个方法(public修饰的)
		2. getMethods();
		得到一个类的所有方法 (public修饰的)
		3. getDeclaredMethod(String methodName , class.. clss)
		根据参数列表的类型和方法名, 得到一个方法(除继承以外所有的:包含私有, 共有, 保护, 默认)
		4. getDeclaredMethods();
		得到一个类的所有方法 (除继承以外所有的:包含私有, 共有, 保护, 默认)
		5.invoke(Object o,Object... para) :
		调用方法 ,
		参数1. 要调用方法的对象
		参数2. 要传递的参数列表
		6.getName()
		获取方法的方法名称
		7.setAccessible(boolean flag)
		如果flag为true 则表示忽略访问权限检查 !(可以访问任何权限的方法)
		//拿到类对象
        Class<Person2> person2 = (Class<Person2>) Class.forName("Person2");
        //拿到类对象的无参构造器
        Constructor<Person2> constructor = person2.getConstructor();
        //创建对象实例
        Person2 p2 = constructor.newInstance();
        //通过构造器拿到方法
        Method setName = person2.getMethod("setName", String.class);
        //参数1:那个对象要执行setName方法
        //参数2:调用时要传递的方法
        Object p = setName.invoke(p2, "张三");

7.反射中拿到字段

		1. getDeclaredField(String filedName)
		根据属性的名称, 获取一个属性对象 (所有属性)
		2. getDeclaredFields()
		获取所有属性
		3. getField(String filedName)
		根据属性的名称, 获取一个属性对象 (public属性)
		4. getFields()
		获取所有属性 (public)
		5. get(Object o );
		参数: 要获取属性的对象
		获取指定对象的此属性值
		6. set(Object o , Object value)
		参数1. 要设置属性值的 对象
		参数2. 要设置的值
		设置指定对象的属性的值
		7. getName()
		获取属性的名称
		8. setAccessible(boolean flag)
		如果flag为true 则表示忽略访问权限检查 !(可以访问任何权限的属性)
		public static void main(String[] args) throws Exception{
        Class p = Class.forName("Person2");
        Constructor constructor = p.getConstructor();
        Object o = constructor.newInstance();
        Field field = p.getField("name");
        //给o对象的name字段赋值为张三
        field.set(o,"张三");
        System.out.println(o);
    	}

8.注解与反射

我们可以通过反射的方式来拿到类与字段上的注解

		public static void main(String[] args) throws Exception{
        Class b = Class.forName("com.Book");
        TableAnnotation annotation = (TableAnnotation) b.getAnnotation(TableAnnotation.class);
        System.out.println(annotation.value());
        Field[] fields = b.getDeclaredFields();
        for (Field field : fields) {
            ColumnAnnotation annotation1 = field.getAnnotation(ColumnAnnotation.class);
            System.out.println(field.getName()+"属性的字段注解为"+annotation1.columnName());
        }
    }

总结

提示:完结

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值