Java反射入门

一. 反射
	a. 类的加载时机
		i. 创建类的实例
		ii. 调用类的静态变量,或者为静态变量赋值
		iii. 调用类的静态方法
		iv. 使用某个类的子类
		v. 直接使用java.exe命令来运行某个主类
		vi. 使用反射强制加载某个类,并生成class对象
	b. 类加载器
		i. 类加载器:是负责将磁盘上的某个class文件读取到内存并生成Class的对象。
		ii. Java中有三种类加载器
			1) 启动类加载器(Bootstrap ClassLoader):用于加载系统类库<JAVA_HOME>\bin目录下的class,例如rt.jar。
			2) 扩展类加载器(Extension ClassLoader):用于加载扩展类库<JAVA_HOME>\jre\lib\ext目录下的class。
			3) 应用程序类加载器(Application ClassLoader):用于加载我们自定义类的加载器
		iii. 双亲委派机制
			1) 当某个类加载器需要加载一个类时,它并不是直接去加载,而把加载的需要交给父级类加载器,最终请求会达到到达启动类加载器,启动类加载判断是否可以加载该类,如果加载不了再交给扩展类加载器,扩展类加载判断是否可以加载,如果加载不了,再交给应用程序类加载器.
		iv. 双亲委派机制的好处
			1) 确保了一个类只加载一次
	c. 反射
		i. 反射就是在程序运行时获取一个类的Class对象(字节码文件对象),解剖它,取出其中的各种成员,使用这些成员
		ii. 作用:
			1) 开发"IDEA"等之类的IDE
			2) 学习各种框架的设计和底层原理: Spring,SpringMVC,Mybatis,... 
		iii. 反射中万物皆对象的概念
			1) Class对象	某个字节码文件 
			Field对象	某个成员变量
			Method对象	某个成员方法
			Constructor对象	某个构造方法
			newInstance	创建对象
			invoke	调用/执行  
		iv. 体验一下反射的语法
			1) 创建对象:
				a) 正常语法: new 构造方法(参数);
				b) 反射语法: 构造方法对象.newInstance(参数); 
			2) 调用方法:
				a) 正常语法: 对象名.成员方法名(参数);
				b) 反射语法: 成员方法对象.invoke(对象名,参数);
		v.  反射的第一步获取字节码文件对象
		代码演示
		public class GetClass02 {
		    public static void main(String[] args) throws ClassNotFoundException {
		        //获取一个类的Class对象的三种方式
		        //1.通过类的一个静态成员class
		        Class dogClass = Dog.class;
		        System.out.println(dogClass);
		        //2.通过该类的一个对象,获取该类的class对象
		        Dog dog = new Dog();
		        Class dogClass1 = dog.getClass();
		        System.out.println(dogClass1);
		        //3.通过反射强制加载该类,并获取该类的Class对象
		        Class dogClass3 = Class.forName("demo_class01.Dog");
		        System.out.println(dogClass3);
		        System.out.println(dogClass == dogClass1);
		        System.out.println(dogClass == dogClass3);
		        System.out.println(dogClass1 == dogClass3);
		    }
		}
		vi.  Class对象中的三个方法
			1) public String getName();
			2) public String getSimple();
			3) public Object newInstance();
		代码演示
		public class ClassMethod01 {
		    public static void main(String[] args) throws Exception{
		        Class dogClass = Dog.class;
		        //1.获取全限定类名
		        System.out.println(dogClass.getName());
				//打印结果:demo_class01.Dog
		        //2.获取类名
		        System.out.println(dogClass.getSimpleName());
				//打印结果:Dog
		        //3.创建Class对象所代表的那个类的对象,底层实际上使用Dog的无参构造
		        Object o = dogClass.newInstance();
				//打印结果:Dog{name='null', age=0}
		        System.out.println(o);
		    }
		}
		vii. 通过反射获取构造方法&&使用构造方法创建对象
			1) 反射获取构造方法
				a) public Constructor getConstructor(Class…parameterTypes);获取单个"public"构造
				b) public Constructor getDeclaredConstructor(class…parameterTypes);获取单个"任意修饰"构造
				c) public Constructor[] getConstructors();获取所有"public"构造
				d) public Constructor[] getDeclaredConstructors();获取所有"任意修饰"构造
			2) 使用构造方法创建对象
				a) 语法:构造方法对象.newInstance(参数);
				b) 私有构造必须先设置暴力权限,然后才能正常使用,否则抛出IllegalAccessException异常
		viii. 通过反射获取成员方法&&调用成员方法
			1) 反射获取成员方法
				a) public Method getMethod(String name,Class...args);获取"public"方法
				b) public Method getDeclaredMethod(String name,Class...args);获取"任意修饰"方法
				c) public Method[] getMethods(); 获取所有"public"方法,包括父类继承的
				d) public Method[] getDeclaredMethods(); 获取所有"任意修饰"方法,不包含父类继承的
			2) 调用成员方法
				a) 格式:成员方法对象.invoke(对象名,参数);
				b) 私有成员方法不能直接调用,必须先设置暴力访问权限,否则抛出IllegalAccessException异常
二. 注解
	a. 介绍
		i. 注解是JDK1.5的新特性(注解,增强for,泛型,可变参数)
		ii. 注解相当一种标记,是类的组成部分,可以给类携带一些额外的信息
		iii. 标记(注解),可以用在各种地方(包,类,构造方法,普通方法,成员变量,局部变量,...)
		iv. 注解,主要是给编译器或者JVM看的,用于完成某些特定的功能
	b. 作用
		i. 给程序带入一些参数 
		ii. 编译检查  
		iii. 给框架使用,作为框架的配置文件
	c. 常见的注解介绍
		i. @author:	用来标识作者名
		@version:	用于标识对象的版本号  
		@Override: 	用于标识该方法是重写的   
		@deprecated: 	用于标识过期的API
		@Test: 	用于单元测试的注解
	d. 自定义注解(Annotation)
		i. 自定义类:	public class 类名
		自定义接口:	public interface 接口
		自定义枚举:	public enum 枚举名
		自定义注解: 	public @interface 注解名
	e. 给自定义注解添加属性
		i. 格式:
			public @interface 注解名{
		        //注解内部只有属性,没有别的!!
		        数据类型 属性名();
		        数据类型 属性名() [default 默认值];
		    }
		ii. 注解中并不是所有数据类型都可以的!!!
		    只能是以下三大类型:
			1) 八大基本类(byte,short,char,int,long,float,double,boolean)
			2) String,Class,注解类型,枚举类 
			3) 以上12具体数据类型的数组  
	f. 使用注解时的注意事项
		i. 使用格式:
			@注解名(属性名=属性值,属性名=属性值)
		ii. 注意:
			1) 使用注解时保证注解的每个属性都必须有值(有默认值我们可以不再赋值,没有默认值我们必须赋值)
			2) 如果是数组需要使用{}把值括起来,如果数组的值只有一个,那么大括号可以省略
		iii. 特殊属性名value
			1) 如果注解中"只有一个属性",并且名字叫做"value",那么使用时可以直接写属性的值,省略属性名
			2) 如果注解中有value之外的其他属性,那么其他属性都有默认值,且使用注解时只给value赋值,那么直接写属性的值,省略属性名.
	g. 注解的注解--元注解
		i. @Target 元注解
			1) 作用:用来标识注解使用的位置,如果没有标识,那么我们的注解在各种地方都可以使用
			2) 取值:必须使用ElementType枚举下的值:
				TYPE,类,接口 
			     FIELD, 成员变量
			     METHOD, 成员方法 
			     PARAMETER, 方法参数 
			     CONSTRUCTOR, 构造方法 
			     LOCAL_VARIABLE, 局部变量
			3) 代码演示
			//使用元注解修饰我们定义的注解            
			@Target({ElementType.FIELD,ElementType.METHOD})
			public @interface MyAnno {
			}
			
			//使用我们定义的注解
			@MyAnno//报错
			public class Demo {
				@MyAnno
				private int age;
				@MyAnno
				private String name;
		
				@MyAnno//报错
				public Demo() {
				}
				@MyAnno//报错
				public Demo(@MyAnno int age,@MyAnno String name) {
					this.age = age;
					this.name = name;
				}
				@MyAnno
				public void show(@MyAnno int age){//报错
					@MyAnno//报错
					String name = "张三";
					System.out.println(age);
				}
			}
		ii. Retention元注解
			1) 作用:用来标识我们注解的生命周期
			2) 取值:必须是RetentionPolicy枚举中的下面三个值之一
				a) SOURCE表示我们的注解只在源码阶段存在,编译成字节码文件后删除
				b) CLASS表示我们的注解在源码阶段和字节码阶段存在,加载到内存后删除
				c) RUNTIME表示我们的注解在源码阶段,字节码阶段,运行时都存在(永远不删除) 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值