细说java反射

1.   先说第一句话,这个话非常非常重要!

java里,无论生成某个类的多少对象,这些对象都会对应于同一个Class对象。

2.   再说第二句话,java反射有什么用?

这么说吧,其实java类的成员变量、方法是不是private没有关系,运用反射就完全可以玩转类的私有变量和私有方法。正是因为反射的这两部分使用才有了hibernatespring等那些框架,换言之,没有反射就没有框架!

3.   到底java反射有什么具体的作用?

总说:Java的反射机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息(所有信息)。

分说:

(1) 运行时判断任意一个对象所属的类

(2) 运行时构造任意一个类的对象

(3) 运行时判断任意一个类所具有成员变量和方法

(4) 运行时调用任意一个对象的方法

注意:全是运行时,java反射是运行时的行为。

 

写代码诠释java反射最直观了,没有之一。下面是我写的例子,代码写了很多注释来增加理解。

package com.lzg.reflection;

public class User {
	private int id;
	private String name;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + "]";
	}
	public static void main(String[] args) {
		User user = new User();
		user.setId(1);
		user.setName("hello");
		System.out.println(user);
		
	}
}

package com.lzg.reflection;

public class UserDaoImpl {

	public int id;
	private String name;
	
	private String waihao = "胖子";// 外号
	
	public UserDaoImpl() {
		super();
	}
	
	public UserDaoImpl(int id, String name) {
		super();
		this.id = id;
		this.name = name;
	}

	@Override
	public String toString() {
		return "UserDaoImpl [id=" + id + ", name=" + name + "]";
	}

	public User getUserById(int userId) {
		//获取User的数据用新建模拟了
		User user = new User();
		user.setId(100);
		user.setName("lzg");
		return user;
	}
	
	public int add(int a, int b) {
		return a + b;
	}
	
	private String sayHello(String name) {
		return "hello:" + name;
	}
	
	public String sayWaihao() {
		return waihao;
	}
}

package com.lzg.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectionClient {
	
	public static void main(String[] args) throws Exception {
		//要想使用反射,首先需要获得待处理类或对象所对应的Class对象
		/**
		 * 获取某个类或对象所对应的Class对象的3种方式
		 * 1. Class classType = UserDaoImpl.class;
		 * 2. Class classType = Class.forName("com.lzg.reflection.UserDaoImpl"); 
		 * 3. 
		 * UserDaoImpl userDaoImpl = new UserDaoImpl();
		 * Class classType2 = userDaoImpl.getClass();
		 */
		Class classType = Class.forName("com.lzg.reflection.UserDaoImpl"); 
		
		//反射获取类的构建方法并使用,分带参数的和不带参数的。
		//不带参数的
		Object userDaoImplObject = classType.newInstance(); 
		//带参数的
		Constructor userDaoImplConstructor = classType.getConstructor(new Class[]{int.class, String.class});
		UserDaoImpl userDaoImplOjbect2 = (UserDaoImpl) userDaoImplConstructor.newInstance(new Object[]{1001, "UserDaoImplName"});
		System.out.println(userDaoImplOjbect2);
		
		System.out.println("----------");
		
		//反射获取UserDaoImpl.java所有声明的方法
		Method[] userDaoImplMethods = classType.getDeclaredMethods();
		
		for(Method method: userDaoImplMethods) {
			System.out.println(method);
		}
		
		System.out.println("----------");
		
		//反射获取具体方法并使用
		Method addMethod = classType.getMethod("add", new Class[]{int.class, int.class});
		int addResult = (int) addMethod.invoke(userDaoImplObject, new Object[]{1, 3});
		System.out.println(addResult);
		
		System.out.println("----------");
		
		//反射获取对象的成员变量
		//getField()要求该成员变量属性是公有的
		Field idField = classType.getField("id");
		System.out.println(idField.getName());
		System.out.println("");
		//getFields()只能获取所有公有属性的成员变量
		Field[] fields = classType.getFields();
		for(Field field : fields) {
			System.out.println(field.getName()); 
		}
		System.out.println("");
		//不在于成员变量的属性是否公有
		Field nameField = classType.getDeclaredField("name");
		System.out.println(nameField.getName());
		System.out.println("");
		//获取所有成员变量
		Field[] fields2 = classType.getDeclaredFields();
		for(Field field : fields2) {
			System.out.println(field.getName());
		}
		
		System.out.println("----------");
		
		/**
		 * 其实java类的成员变量、方法是不是private没有关系,运用反射就完全可以玩转类的私有变量和私有方法。
		 * 实用部分,反射调用对象的私有方法、反射访问对象的私有成员变量。
		 * 实用在哪?这么说吧,正是因为反射的这两部分使用才有了hibernate、spring等那些框架,换言之,没有反射就没有框架!
		 */
		//反射调用对象的私有方法
		Method sayHelloMethod = classType.getDeclaredMethod("sayHello", new Class[]{String.class});
		sayHelloMethod.setAccessible(true); //放开压制Java的访问控制检查
		String sayHelloResult = (String) sayHelloMethod.invoke(userDaoImplObject, new Object[]{"lzg"});
		System.out.println(sayHelloResult);
		
		//反射访问对象的私有成员变量
		Field waihaoField = classType.getDeclaredField("waihao");
		waihaoField.setAccessible(true); //放开Java对访问修饰符访问控制检查
		waihaoField.set(userDaoImplObject, "瘦子");
		//调用方法测试一下是否更改了private成员变量,只是测试,就不用反射了。
		System.out.println(((UserDaoImpl)userDaoImplObject).sayWaihao());
	
	}
}

RelectionClient运行结果:

UserDaoImpl [id=1001, name=UserDaoImplName]
----------
public int com.lzg.reflection.UserDaoImpl.add(int,int)
public java.lang.String com.lzg.reflection.UserDaoImpl.toString()
private java.lang.String com.lzg.reflection.UserDaoImpl.sayHello(java.lang.String)
public com.lzg.reflection.User com.lzg.reflection.UserDaoImpl.getUserById(int)
public java.lang.String com.lzg.reflection.UserDaoImpl.sayWaihao()
----------
4
----------
id
**********
id
**********
name
**********
id
name
waihao
----------
hello:lzg
瘦子


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 8之后的ConcurrentHashMap在底层实现上进行了一些改进,主要包括以下两个方面: 1. 数据结构的改进:Java 8之前的ConcurrentHashMap使用了分段锁的方式实现并发控制,内部结构是由多个Segment(段)组成的数组。而Java 8及以后的版本中,引入了一种称为"扁平化"(Flattening)的方式来提高并发性能。它将整个数据结构分成了多个独立的桶(Bucket),每个桶内部都是一个链表或红黑树的结构,用于存储键值对。这种扁平化的数据结构减少了锁的粒度,提高了并发性能。 2. 使用CAS操作:Java 8之后的ConcurrentHashMap在并发控制方面使用了CAS(Compare and Swap)操作。CAS是一种乐观锁技术,通过比较并交换的方式来实现线程间的同步。它不需要使用传统的锁机制,避免了线程阻塞和上下文切换的开销,可以提高并发性能。 具体来说,Java 8之后的ConcurrentHashMap采用了以下策略: - 在读取操作(如get)时,不需要加锁,可以实现高效的并发读取。 - 在更新操作(如put、remove)时,使用CAS操作进行原子性的操作,避免了加锁的开销。 - 在冲突(多个线程同时操作一个桶)发生时,采用自旋和重试的方式进行处理,以保证数据的一致性。 总之,Java 8之后的ConcurrentHashMap通过改进数据结构和使用CAS操作,提高了并发性能和可伸缩性。它在高并发场景下具有更好的性能表现,并且保证了数据的一致性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值