《Java反射总结》-(很重要)

目录

一,反射的定义

二,反射的用途

三,反射的基础知识

四,代理模式


一,反射的定义

Java反射是指在运行时获取一个类的信息并操作该类的成员(字段、方法、构造函数等)的能力。

这里我们就要谈谈java的运行期编译期指的是什么:

        1.编译期:将磁盘里的java源文件编译成字节码文件,编译期只是做了一些翻译功能,并没                             有把代码放在内存中运行起来。

        2.运行期:java虚拟机会将磁盘里的字节码文件转换成机器码,交给                                                             计算机执行,直到程序运行结束。所谓运行期就把在磁盘中的代码 放到                                           内存中执行起来。

二,反射的用途

通过反射,我们可以在运行时动态地创建对象、调用方法、访问字段等,而不需要在编译时确定这些操作。

三,反射的基础知识

1.获取Class对象:可以通过对象的getClass()方法或者类名.class来获取一个类的Class对象,也可以通过Class.forName("类名")来获取某个类的Class对象。

Class常用方法 :

类型访问方法返回值类型说明
包路径getPackage()

Package 对象

获取该类的存放路径
类名称getName()

String 对象

获取该类的名称
继承类getSuperclass()Class 对象获取该类继承的类
实现接口getlnterfaces()

Class 型数组

获取该类实现的所有接口
构造方法

getConstructors()

getDeclaredContruectors()

Constructor 型数组

Constructor 对象

获取所有权限为 public 的构造方法

获取当前对象的所有构造方法

方法

getMethods()

getDeclaredMethods()

Methods 型数组

Methods 对象

获取所有权限为 public 的方法

获取当前对象的所有方法

成员变量

getFields()

getDeclareFileds()

Field 型数组

Field 对象

获取所有权限为 public 的成员变量

获取当前对象的所有成员变量

2.创建对象:通过Class对象的newInstance()方法可以创建一个类的实例,相当于调用了该类的无参构造函数。如果需要调用有参构造函数,可以通过先获取构造函数对象再调用newInstance()方法来实现。

public class Demo15 {
	public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
		Class cls = Order1.class;
		Order1 order = (Order1)cls.newInstance();
		System.out.println(order);
		
		Constructor con = cls.getConstructor(int.class);
		Order1 order2 = (Order1)con.newInstance(100);
		System.out.println(order2);
	}
}

class Order1{
	private String orderNo;
	private LocalDateTime time;
	
	public Order1() {
		this.orderNo = UUID.randomUUID().toString();
		this.time = LocalDateTime.now();
		
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	public Order1(int a) {
		System.out.println("这是Order类的有参构造");
	}

	@Override
	public String toString() {
		return "Order [orderNo=" + orderNo + ", time=" + time + "]";
	}

	public String getOrderNo() {
		return orderNo;
	}

	public void setOrderNo(String orderNo) {
		this.orderNo = orderNo;
	}

	public LocalDateTime getTime() {
		return time;
	}

	public void setTime(LocalDateTime time) {
		this.time = time;
	}
}

 3.访问字段:通过Field类的对象可以访问某个类的字段。可以使用getDeclaredFields()方法获取所有字段的数组,然后通过Field对象的get()和set()方法来读取和修改字段的值。

// 反射操作 访问字段(成员变量)
public class Demo07 {
	public static void main(String[] args) {
		Class cls = Book.class;
		
		// 所有Public访问修饰符
		//Field[] fields = cls.getFields();
		
		Field[] fields = cls.getDeclaredFields();
		for(Field f : fields) {
			System.out.println("成员变量访问修饰符(int):"+f.getModifiers());
			System.out.println("成员变量访问修饰符:"+Modifier.toString(f.getModifiers()));
			System.out.println("成员变量类型:"+f.getType());
			System.out.println("成员变量名称:"+f.getName());
		}
	}
}

class Book{
	public String bookName;
	public int count;
	private double prince;
	private String address;
	
	public Book() {
	}

	public void dosth(int a, double b, String c) {
		
	}
	
	public String getBookName() {
		return bookName;
	}

	public void setBookName(String bookName) {
		this.bookName = bookName;
	}

	public int getCount() {
		return count;
	}

	public void setCount(int count) {
		this.count = count;
	}

	public double getPrince() {
		return prince;
	}

	public void setPrince(double prince) {
		this.prince = prince;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	@Override
	public String toString() {
		return "Book [bookName=" + bookName + ", count=" + count + ", prince=" + prince + ", address=" + address + "]";
	}
}

3.调用方法:通过Method类的对象可以调用某个类的方法。可以使用getDeclaredMethods()方法获取所有方法的数组,然后通过Method对象的invoke()方法来调用具体的方法。

// 反射操作(获取方法)
// 每一个方法都会被封装成一个Method对象。
public class Demo10 {

	public static void main(String[] args) {
		Class cls = Book.class;
		
		// 包含父类中的方法
		// Method[] methods = cls.getMethods();
		
		// 获取所有定义的方法(仅包含当前类)
		Method[] methods = cls.getDeclaredMethods();
		
		for(Method m : methods) {
			System.out.println(m.getName());
			System.out.println(Modifier.toString(m.getModifiers()));
			System.out.println();
			
			// 获取所有参数类型
			//Class[] paraType = m.getParameterTypes();
			
			Parameter[] paraType = m.getParameters();
			for(Parameter p : paraType) {
				System.out.println(p.getName());
				System.out.println(p.getType());
				System.out.println("----------------------");
			}
		}
	}
}

4.获取父类和接口:通过Class对象的getSuperclass()方法可以获取一个类的父类,通过getInterfaces()方法可以获取一个类实现的接口。

5.修饰符和注解:通过Class对象可以获取一个类的修饰符(如public、private等)和注解信息。返回方法的修饰符,它是一个 int ,不同的 value 表示不同的访问修饰符。

四,代理模式

给某一个对象提供一个代理,并由代理对象来控制对真实对象的访问。代理模式是一种结构型 设计模式。

1,静态代理

静态代理:由程序员创建或特定工具自动生成源代码,也就是在编译时就已经将接口、被代理类、代理类等确定下来在程序运行之前,代理类的.class文件就已经生成。

如上图所示的代码实现如下:

public class Client {

	public static void main(String[] args) {
		Subject subject = new SubjectProxy();
		subject.request();
	}
}
public interface Subject {
	void request();
}
public class RealSubject implements Subject{
	public RealSubject() {}
	@Override
	public void request() {
		System.out.println("业务逻辑1");
		System.out.println("业务逻辑2");
		System.out.println("业务逻辑3");
	}
}
public class SubjectProxy implements Subject{
	
	private Subject terget;
	
	public SubjectProxy() {
		terget = new RealSubject();
	}
	
	public void request() {
		System.out.println("begin-------------");
		terget.request();
		System.out.println("end---------------");
	}
}

 运行结果如下:

2,动态代理

代理类在程序运行时创建的代理方式被成为动态代理。

我们上面静态代理的例子中,代理类(SubjectProxy)是自己定义好的,在程序运行之前就已经编译完成。然而动态代理,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。 比如说,想要在每个代理的方法前后都加上一个处理方法。

public class Client {
	public static void main(String[] args) {
		// 将创建被代理的对象(UserService接口的实现类)传入我们动态代理的方法中
		LogInvocationHandlerImpl hander = new LogInvocationHandlerImpl(new UserServiceImpl());
		LogInvocationHandlerImpl hander1 = new LogInvocationHandlerImpl(new RealSubject());
		
		// 创建目标对象
		RealSubject realSubjectTagter = new RealSubject();
		
		// 创建UserService动态代理对象
		UserService proxy = (UserService)Proxy.newProxyInstance(
									UserService.class.getClassLoader(),
									new Class[] {UserService.class},
									hander);
		Subject proxy1 = (Subject)Proxy.newProxyInstance(
									realSubjectTagter.getClass().getClassLoader(),
									realSubjectTagter.getClass().getInterfaces() , 
									hander1);
		
		proxy.select();
		proxy1.request();
		
		System.out.println(proxy.getClass());
		System.out.println(proxy1.getClass());
	}
}
// InvocationHandler接口的实现类:代理类中扩展逻辑,抽取封装
public class LogInvocationHandlerImpl implements InvocationHandler {

	private Object tager;
	
	public LogInvocationHandlerImpl(Object tager) {
		this.tager = tager;
	}
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.printf("%s方法开始--------------\n",method.getName());
		
		// 执行目标对象的目标方法(反射)
		Object returnValue = method.invoke(tager, args);
		
		System.out.printf("%s方法结束--------------\n",method.getName());
		
		return returnValue;
	}
}
// 真正的实现类
public class UserServiceImpl implements UserService {
	@Override
	public void select() {
		System.out.println("select * ..................");
		System.out.println("数据库中完成用户信息的查询执行!");
	}

	@Override
	public void update() {
		System.out.println("update ...................");
		System.out.println("数据库中用户状态的更新执行!");
	}
}
public interface UserService {
	void select();
	void update();
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值