欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

我的Java SE总结(十)

程序员文章站 2022-07-14 20:25:26
...

注解和反射

反射
概念
1.反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力;
2.在运行时期,动态地去获取类中的信息(类的信息,方法信息,构造器信息,字段等信息);

作用
1.增加程序的灵活性,避免将程序写死到代码里(解除硬编码的问题
2.Java的反射机制它知道类的基本结构,可以动态的去获取类这样的结构的结构
3.可以让程序员在不知道其它程序员会有什么类的时候就编写完成自己的代码

优缺点
反射的优点:灵活,功能强大(可以拿到私有的…)
反射的缺点:破坏封装,影响性能

语法使用
1. 获取字节码文件 : 获取字节码文件的目的就是为了获取字节码中的字段、构造方法、普通方法等

1.1 Class clazz  = Class.forName(全限定路径名) //(最多使用)默认调用的方法
1.2 static Class<?> forName(String name, boolean initialize, ClassLoader loader)  
							/*name:全限定路径名
							initialize:表示是否初始化,默认是
							loader:可以指定一个类加载器加载字节码文件*/
1.3. 全限定类名.class		//前提是类已经设计好了
1.4. 对象名.getClass()	    //前提是类已经设计好了
Class类中方法newInstance()//创建当前字节码对象(只能调用无参且是public修饰的构造方法)
  1. 根据字节码文件获取构造方法、普通方法、字段等

    构造方法 (获取构造方法的目的就是为了创建对象)
    创建对象的目的是:调用非静态的成员(成员变量、普通方法)

Constructor[] constructors = clazz.getConstructors() //获取public修饰的构造方法数组
Constructor[] constructors = clazz.getDeclaredConstructors() //获取任意权限的所有造方法数组
Constructor constructor = clazz.getConstructor(Class 参数字节码)//根据参数类型获取public修饰指定的的构造方法
Constructor constructor = clazz.getDeclearConstructor(Class  参数字节码) //获取任意访问权限指定的构造方法
Object instance  = constructor.newInstance(Object...实参);//可以创建任意访问权限的有参或者无参构造

普通方法 (获取普通方法的目的就是为了被 对象或者 类调用 执行)

Method[] methods = clazz.getMethods() //获取public修饰的构造方法数组,有父类中的方法
Method[] methods = clazz.getDeclaredMethods() //获取任意访问权限所有造方法数组,并且都是自己的方法
Method method = clazz.getMethod(String methodName,Class... 参数字节码)/*根据方法名和参数类型获取指定的的方法.methodName:方法名,Class:形参类型。如果方法没有形参,则Class可变参数不用写*/
Method method = clazz.getDeclaredMethod(String methodName,Class... 参数字节码)/*根据方法名和参数类型获取指定的的方法.methodName:方法名,Class:形参类型。如果方法没有形参,则Class可变参数不用写*/
				
//通过普通方法对象调用执行方法
method.invoke(Object obj,Object... args);
/*obj:对象。如果是对象的方法,就传入一个当前字节码创建的对象,如果是static方法,则写null
args:就是具体实参*/

字段 (获取字段 的目的就是为了被 对象或者 类 赋值取值)

Field[] fields = clazz.getFields() //获取public修饰的字段
Field[] fields = clazz.getDeclaredFields() //获取任意权限所有字段
Field field = clazz.getDeclaredField(String fieldName) //根据字段名获取任意访问权限的指定字段
Field field = clazz.Field(String fieldName)//根据字段名获取public的指定字段

//通过当前的字段对象给某一个字段取值
field.get(Object obj);//如果是属于非static,就传入一个对象,如果是静态的,就传入null。obj:对象
//给某一个字段赋值
field.set(Object obj, Object value);//如果是属于非static,就传入一个对象,如果是静态的,就传入null。obj:对象,value:值

其他方法

String getName()  //获取全限定类名(全限定,包含包名)	Class类中方法
String getSimpleName()  // 获取类名简称			Class类中方法
Package getPackage()   //获取包名				Class类中方法
T newInstance()  //根据当前字节码创建对应的对象		Class类中方法
Annotation[] getAnnotations()   //根据当前字节码获取所有的注解	(类上的注解)

注意:

  •  	1. Class类中方法newInstance():创建当前字节码对象(只能调用无参且是public修饰的构造方法)
    
  •  	2. Constructor类中方法newInstance(Object 实参);//可以创建任意访问权限的有参或者无参构造
    
  •  	3. 私有化方法、字段、构造方法都必须破坏封装才能使用:public void setAccessible(boolean flag) true表示破坏封装,false是不破坏	
    
  •  		是哪个private修饰的方法、字段、构造方法需要执行,就需要用这个对象破坏哪一个的封装
    
  •  		例如:
    
//获取cn.itsource.reflect.User字节码文件
Class<?> clazz = Class.forName("cn.itsource.reflect.User");
//获取User的有String参构造
Constructor<?> constructor = clazz.getConstructor(String.class);
//调用有参String构造,创建一个User对象
Object newInstance = constructor.newInstance("某文");
//获取private修饰的方法:testPrivate
Method method2 = clazz.getDeclaredMethod("testPrivate");
method2.setAccessible(true);//破坏普通方法Method封装

//破坏封装后就可以执行了
Object invoke2 = method2.invoke(newInstance);//没有形参就不用写
System.out.println(invoke2);
  •  	4. 调用static方法、字段:
    
  •  		例如:
    
Field field = clazz.getDeclaredField("country");//获取任意访问权限静态变量country
field.set(null, "中国");//因为字段country是static修饰,所以不用对象调用,就传入null。字段country赋值:中文
Object object = field.get(null);//字段country取值
System.out.println(object);	
		5. 反射是在该类还没有设计好的时候,可以保证继续向后开发
		 	只是保证功能开发完成,运行的话就必须时候整个项目开发完毕才可以
		 	而项目真正运行的时候,肯定所有的项目中的类都已经设计完毕,这时候,就可以保证代码正常运行了	
		
		6. Class类 和它的实例的产生: Class的对象是已经存在的类型,
			所以不能够直接new一个Class对象出来,是通过Class类中的一个方法获取到的。
			例如:通过全限定路径类名
		
		7. 同一种类型不管通过什么方式得到Class的实例都是相等的;一个类型的字节码对象只有一份,在元空间。

注解
概念
是一个标签,有标签后,就具有某一些标签的特性。本质就是跟类、接口、枚举平级的新结构

作用
1. 帮助程序员校验代码。
2. 可以提高开发效率和程序的扩展性【框架技术】
3. 可以生成文档说明 api
生成说明的步骤:
3.1 选中项目/代码,右键选中Export
3.2 输入Javadoc
3.3 第一个next(可以设置生成文档注释的目录),第二个next,设置字符集
如果是UTF-8编码,且有中文,请输入-encoding UTF-8 -charset UTF-8
3.4 勾选一个生成完毕后,直接通过浏览器打开的选项

使用注解
定义好的标签
直接@+标签名即可
使用自定义的标签
需要添加元注解

元注解
[email protected]
用来限制被修饰注解的使用范围,即注解可以在类的哪些成员上使用
[email protected]
限制注解的作用时间
注解的生命周期和三个阶段有关:源代码阶段、CLASS文件中有效、运行时有效,
故其取值也就三个值,分别代表着三个阶段
[email protected] :文档注解,可以使用javadoc生成文档注释
[email protected]:从该类的子类上可以继承父类的注解
假设一个注解在定义时,使用了@Inherited,然后该注解在一个类上使用,
如果这个类有子类,那么通过反射我们可以从类的子类上获取到同样的注解

自定义注解声明步骤
1. 创建一个注解类@Annotation
2. 在类上用元注解修饰
3. 描述注解的取值(声明一些属性)

内置注解
@Override
注解用于标识方法重写,帮助我们校验代码
@Deprecated
注解用于标识方法已过时,只要是在版本迭代中使用。
@SuppressWarnings
注解用于抑制编译器警告,直白的讲就是消除Eclipse上那条黄色警告线
@SafeVarargs
抑制堆污染警告(单独警告),直白的讲就是使用泛型和可变参数搭配使用将会产生的
编译器警告,可以使用@SuppressWarnings消除警告