Java高级基础_反射,注解

反射

反射机制

编译器:将Java代码编译成class文件的过程,该过程只是把代码当作文本进行操作,比如检查错误

运行期:将class文件放入内存中执行

反射机制:在程序运行状态下,对于任意一个类,都能知道这个类的所有属性和方法;对于任意一个对象,都能调用它的任意方法和属性,对于这种动态获取信息以及动态调用对象方法的功能称为Java的反射机制

java.lang.Class类

要知道一个类的属性和方法,必须先获取该类的字节码文件对象。获取类的信息时,使用的就是Class类中的方法,所以先要获取到每一个字节码文件(.class)对应的Class类型的对象,Class类的一个实例表示Java的一种数据类型。Class没有公有的构造方法,Class实例是由JVM在类加载时自动创建的

类型访问方法返回值类型说明
包路径getPackage()Package 对象获取该类的存放路径
类名称getName()String 对象获取该类的名称
继承类getSuperclass()Class 对象获取该类继承的类
实现接口getlnterfaces()Class 型数组获取该类实现的所有接口
构造方法getConstructors()Constructor 型数组获取所有权限为 public 的构造方法
getDeclaredContruectors()Constructor 对象获取当前对象的所有构造方法
方法getMethods()Methods 型数组获取所有权限为 public 的方法
getDeclaredMethods()Methods 对象获取当前对象的所有方法
成员变量getFields()Field 型数组获取所有权限为 public 的成员变量
getDeclareFileds()Field 对象获取当前对象的所有成员变量
内部类getClasses()Class 型数组获取所有权限为 public 的内部类
getDeclaredClasses()Class 型数组获取所有内部类
内部类的声明类getDeclaringClass()Class 对象如果该类为内部类,则返回它的成员类,否则返回 null

getFields()getMethods()方法时会依次获取权限为public的字段和变量,然后是从父类中继承的成员变量和方法;getDeclareFields()getDeclareMethods()只是获取在本类中定义的成员变量和方法

java.lang.reflect 包

  • Constructor 类:提供类的构造方法信息。
  • Field 类:提供类或接口中成员变量信息。
  • Method 类:提供类或接口成员方法信息。
  • Array 类:提供了动态创建和访问 Java 数组的方法。
  • Modifier 类:提供类和成员访问修饰符信息。

1.Constructor

如果访问指定的构造方法,需要根据该构造方法的入口参数的类型来访问

方法名称说明
isVarArgs()查看该构造方法是否允许带可变数量的参数,如果允许,返回 true,否则返回 false
getParameterTypes()按照声明顺序以 Class 数组的形式获取该构造方法各个参数的类型
getExceptionTypes()以 Class 数组的形式获取该构造方法可能抛出的异常类型
newInstance(Object … initargs)通过该构造方法利用指定参数创建一个该类型的对象,如果未设置参数则表示 采用默认无参的构造方法
setAccessiable(boolean flag)如果该构造方法的权限为 private,默认为不允许通过反射利用 netlnstance() 方法创建对象。如果先执行该方法,并将入口参数设置为 true,则允许创建对 象
getModifiers()获得可以解析出该构造方法所采用修饰符的整数

2.Modifier

静态方法名称说明
isStatic(int mod)如果使用 static 修饰符修饰则返回 true,否则返回 false
isPublic(int mod)如果使用 public 修饰符修饰则返回 true,否则返回 false
isProtected(int mod)如果使用 protected 修饰符修饰则返回 true,否则返回 false
isPrivate(int mod)如果使用 private 修饰符修饰则返回 true,否则返回 false
isFinal(int mod)如果使用 final 修饰符修饰则返回 true,否则返回 false
toString(int mod)以字符串形式返回所有修饰符

3.Method

静态方法名称说明
getName()获取该方法的名称
getParameterType()按照声明顺序以 Class 数组的形式返回该方法各个参数的类型
getReturnType()以 Class 对象的形式获得该方法的返回值类型
getExceptionTypes()以 Class 数组的形式获得该方法可能抛出的异常类型
invoke(Object obj,Object…args)利用 args 参数执行指定对象 obj 中的该方法,返回值为 Object 类型
isVarArgs()查看该方法是否允许带有可变数量的参数,如果允许返回 true,否则返回 false
getModifiers()获得可以解析出该方法所采用修饰符的整数

4.Field

方法名称说明
getName()获得该成员变量的名称
getType()获取表示该成员变量的 Class 对象
get(Object obj)获得指定对象 obj 中成员变量的值,返回值为 Object 类型
set(Object obj, Object value)将指定对象 obj 中成员变量的值设置为 value
getlnt(0bject obj)获得指定对象 obj 中成员类型为 int 的成员变量的值
setlnt(0bject obj, int i)将指定对象 obj 中成员变量的值设置为 i
setFloat(Object obj, float f)将指定对象 obj 中成员变量的值设置为 f
getBoolean(Object obj)获得指定对象 obj 中成员类型为 boolean 的成员变量的值
setBoolean(Object obj, boolean b)将指定对象 obj 中成员变量的值设置为 b
getFloat(Object obj)获得指定对象 obj 中成员类型为 float 的成员变量的值
setAccessible(boolean flag)此方法可以设置是否忽略权限直接访问 private 等私有权限的成员变量
getModifiers()获得可以解析出该方法所采用修饰符的整数
package com.henrik.reflect;

import java.io.Serializable;
import java.util.Date;

public interface ReflectService {
	public String response(String info);
	public Date getTime();
}
class ReflectServiceImpl implements ReflectService{
	@Override
	public String response(String info) {
		return "response"+info;
	}
	@Override
	public Date getTime() {
		return new Date();
	}
}
class ClientCall implements Serializable{
	//版本号:在反序列化期间用于验证序列化对象的发送方和接收方是否为该对象加载了与序列化兼容的类。
	private static final long serialVersionUID = 8316370391638512860L;
	
	private String className; 	//表示类名或接口名
	
	private String methodName;	//表示方法
	private Class<?>[] paramTypes;	//表示方法参数类型
	private Object[] params;	//表示方法参数值
	
	private Object result;		//方法的执行结果
	
	public ClientCall() {}
	public ClientCall(String className,String methodName,Class<?>[] paramTypes,Object[] params) {
		this.className = className;
		this.methodName = methodName;
		this.paramTypes = paramTypes;
		this.params = params;
	}
	
	
	public String getClassName() {
		return className;
	}
	public void setClassName(String className) {
		this.className = className;
	}
	public String getMethodName() {
		return methodName;
	}
	public void setMethodName(String methodName) {
		this.methodName = methodName;
	}
	public Class<?>[] getParamTypes() {
		return paramTypes;
	}
	public void setParamTypes(Class<?>[] paramTypes) {
		this.paramTypes = paramTypes;
	}
	public Object[] getParams() {
		return params;
	}
	public void setParams(Object[] params) {
		this.params = params;
	}
	public Object getResult() {
		return result;
	}
	public void setResult(Object result) {
		this.result = result;
	}
	@Override
	public String toString() {
		return "ClientCall [className=" + className + ", methodName=" + methodName + ", paramTypes=" + paramTypes + ", params=" +params +"]";
	}
}
package com.henrik.reflect;

import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;

public class ReflectServer {
	@SuppressWarnings("resource")
	private void service() throws Exception {
		ServerSocket serverSocket = new ServerSocket(8090);
		while(true) {
			Socket socket = serverSocket.accept();
			InputStream in = socket.getInputStream();
			ObjectInputStream ois = new ObjectInputStream(in);
			OutputStream out = socket.getOutputStream();
			ObjectOutputStream oos = new ObjectOutputStream(out);
			ClientCall call = (ClientCall)ois.readObject();
			System.out.println(call);
			call = invoke(call);
			oos.writeObject(call);
			ois.close();
			oos.close();
			socket.close();
		}
	}
	@SuppressWarnings("deprecation")
	private ClientCall invoke(ClientCall call) {
		Object result = null;
		try {
			String className = call.getClassName();
			String methodName = call.getMethodName();
			Class<?>[] paramTypes = call.getParamTypes();
			Object[] params = call.getParams();
			Class<?> classType = Class.forName(className);
			Method method = classType.getMethod(methodName, paramTypes);
			ReflectService remoteObject = (ReflectService)classType.newInstance();
			if(remoteObject == null) {
				throw new Exception(className+"的远程对象不存在");
			}else {
				result = method.invoke(remoteObject, params);
			}
		} catch (Exception e) {
			result = e;
		}
		call.setResult(result);
		return call;
	}
	public static void main(String[] args) throws Exception {
		ReflectServer server = new ReflectServer();
		server.service();
	}
}

package com.henrik.reflect;

import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;

public class ReflectClient {
	public void invoke() throws Exception{
		Socket socket = new Socket("localhost",8090);
		OutputStream out = socket.getOutputStream();
		ObjectOutputStream oos = new ObjectOutputStream(out);
		InputStream in = socket.getInputStream();
		ObjectInputStream ois = new ObjectInputStream(in);
		//创建一个远程调用对象
		ClientCall call = new ClientCall("com.henrik.reflect.ReflectServiceImpl","response",new Class[] {String.class},new Object[] {"Java"});
		oos.writeObject(call);//向服务器发送ClientCall对象
		call = (ClientCall)ois.readObject();
		System.out.println(call.getResult());
		oos.close();
		ois.close();
		socket.close();
	}
	
	public static void main(String[] args) throws Exception {
		new ReflectClient().invoke();
	}
}

注解

注解可以看作代码中的补充信息,是一种描述数据的数据,它本身不会改变程序的运行结果,也不会影响程序运行的性能,注解本质是一种数据类型,是一种接口类型。

使用场景
  • 文档注释/** */中使用,是Java最早提供的注解,比如@see,@param,@return
  • 跟踪代码依赖性,实现替代配置文件功能,现在的框架基本都使用注解方式减少配置文件的数量,比如Spring框架
  • 编译时进行格式检查,比如@Override,如果有该注解的方法没有重写父类方法,编译时会被检查出
Java内置注解

到Java8为止JavaSE提供了11个内置注解:java.lang包中5个基本注解, java.lang.annotation包中6个元注解(自定义注解中会使用,对其它注解进行说明的注解)

1.基本注解

@Override:指定方法重写,用于注解方法

@Deprecated:表示某个元素(类,方法等)已过时,用于注解类,接口,成员方法和成员变量等

@SuppressWarnings:指示该注解修饰的元素及其子元素取消显示指定的编译器警告

关键字用途
all抑制所有警告
boxing抑制装箱、拆箱操作时候的警告
cast抑制映射相关的警告
dep-ann抑制启用注释的警告
deprecation抑制过期方法警告
fallthrough抑制在 switch 中缺失 breaks 的警告
finally抑制 finally 模块没有返回的警告
hiding抑制相对于隐藏变量的局部变量的警告
incomplete-switch忽略不完整的 switch 语句
nls忽略非 nls 格式的字符
null忽略对 null 的操作
rawtypes使用 generics 时忽略没有指定相应的类型
restriction抑制禁止使用劝阻或禁止引用的警告
serial忽略在 serializable 类中没有声明 serialVersionUID 变量
static-access抑制不正确的静态访问方式警告
synthetic-access抑制子类没有按最优方法访问内部类的警告
unchecked抑制没有进行类型检查操作的警告
unqualified-field-access抑制没有权限访问的域的警告
unused抑制没被使用过的代码的警告

@SafeVarargs :指示该注解修饰的元素及其子元素取消显示使用可变参数+泛型参数可能造成的堆污染警告

@FunctionalInterface:指定接口为函数式接口(一个接口中只有一个抽象方法),用于接口

2.元注解

@Documented:修饰的注解类会被JavaDoc工具提取为文档

@Target:描述注解可以使用在什么地方,通过成员变量value(java.lang.annotation.ElementType 枚举类型的数组)进行指定

名称说明
CONSTRUCTOR用于构造方法
FIELD用于成员变量(包括枚举常量)
LOCAL_VARIABLE用于局部变量
METHOD用于方法
PACKAGE用于包
PARAMETER用于类型参数(JDK 1.8新增)
TYPE用于类、接口(包括注解类型)或 enum 声明

Retention:描述注解的生命周期,通过成员变量value(java.lang.annotation.RetentionPolicy 枚举类型)进行指定

名称说明
SOURCE在源文件中有效(即源文件保留)
CLASS在 class 文件中有效(即 class 保留)
RUNTIME在运行时有效(即运行时保留)

@Inherited:描述该注解可以被继承,即父类使用了被@Inherited修饰的注解,那么子类自动具有该注解

@Repeatable:描述该注解可以对同一个程序元素重复注解,即被@Repeatable修饰的注解可以多次在同一个程序元素上使用

@Native:被@Native修饰的变量可以被本地代码引用,常常被代码生成工具使用s

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值