Java反射

2 篇文章 0 订阅
1 篇文章 0 订阅

目录💎💎

一,什么是反射?(反射的概述)

二,Class类

获取Class对象

三种方法

代码示例:

 Student.java

三种方法: 

构造类的实例化对象

通过反射构造一个类的实例方式有2种:

获取类的所有信息

1、获取类中的变量(Field)

Field[] getFields():获取类中所有被public修饰的所有变量 Field getField(Stringname):根据变量名获取类中的一个变量,该变量必须被public修饰 Field[]getDeclaredFields():获取类中所有的变量,但无法获取继承下来的变量 FieldgetDeclaredField(String name):根据姓名获取类中的某个变量,无法获取继承下来的变量

2、获取类中的方法(Method) 

3、获取类的构造器(Constructor) 

反射的优缺点  

反射的应用场景 


一,什么是反射?(反射的概述)

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.

二,Class类

Class 类的实例表示正在运行的 Java 应用程序中的类和接口。也就是jvm中有N多的实例每个类都有该Class对象。(包括基本数据类型)
Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass 方法自动构造的。也就是这不需要我们自己去处理创建,JVM已经帮我们创建好了。

获取Class对象

三种方法

1、类名.class:这种获取方式只有在编译前已经声明了该类的类型才能获取到 Class 对象

Class<HashMap> hashMap= HashMap.class;

2、实例.getClass():通过实例化对象获取该实例的 Class 对象

Map<String, String> hashMap = new HashMap<>();
Class<? extends Map> hashMapClass = hashMap.getClass();

3、Class.forName(“类的全限定名”):通过类的全限定名获取该类的 Class 对象

Class<?> hashMap= Class.forName("java.util.HashMap");

拿到 Class对象后:调用它的方法、获取属性、获取类信息,总之它在你面前就没有隐私了😛😛

代码示例:

 Student.java

public class Student {	
		private String sid;
		private String sname;
		public Integer age;
		
		static{
			System.out.println("加载进jvm中!");
		}
		public Student() {
			super();
			System.out.println("调用无参构造方法创建了一个学生对象");
		}
		public Student(String sid) {
			super();
			this.sid = sid;
			System.out.println("调用带一个参数的构造方法创建了一个学生对象");
		}
		public Student(String sid, String sname) {
			super();
			this.sid = sid;
			this.sname = sname;
			System.out.println("调用带二个参数的构造方法创建了一个学生对象");
		}
		@SuppressWarnings("unused")
		private Student(Integer age) {
			System.out.println("调用Student类私有的构造方法创建一个学生对象");
			this.age = age;
		}
		public String getSid() {
			return sid;
		}
		public void setSid(String sid) {
			this.sid = sid;
		}
		public String getSname() {
			return sname;
		}
		public void setSname(String sname) {
			this.sname = sname;
		}
		public void hello() {
			System.out.println("你好!我是" + this.sname);
		}
		public void hello(String name) {
			System.out.println(name + "你好!我是" + this.sname);
		}
		@SuppressWarnings({ "unused", "deprecation" })
		private Integer add(Integer a, Integer b) {
			return new Integer(a.intValue() + b.intValue());
		}
		@Override
		public String toString() {
			return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + "]";
		}	
	}

三种方法: 

    //1.Class.forName("类的权限命名") 获取Class
	Class<Student> clazz =(Class<Student>)Class.forName("com.reflect.Student");
		
	//2. 类.class
	Class clazz02 = Student.class;
			
	//3. 对象.getClass()
	Student stu = new Student();
	Class clazz03 = stu.getClass();

构造类的实例化对象

通过反射构造一个类的实例方式有2种:

1、Class 对象调用newInstance()方法

Class<?> hashMapClass = Class.forName("java.util.HashMap");
HashMap hashMapInstance = (HashMap) hashMapClass.newInstance();

注意:即使 HashMap已经显式定义了构造方法,通过 newInstance() 创建的实例中,所有属性值都是对应类型的初始值,因为 newInstance() 构造实例会调用默认无参构造器。

2、Constructor 构造器调用newInstance()方法

Class<?> hashMapClass = Class.forName("java.util.HashMap");
Constructor<?> constructor = hashMapClass.getConstructor();
constructor.setAccessible(true);
HashMap newInstance = (HashMap) constructor.newInstance();

通过 getConstructor(Object… paramTypes) 方法指定获取指定参数类型的 Constructor, Constructor 调用 newInstance(Object… paramValues) 时传入构造方法参数的值,同样可以构造一个实例,且内部属性已经被赋值。

通过Class对象调用 newInstance() 会走默认无参构造方法,如果想通过显式构造方法构造实例,需要提前从Class中调用getConstructor()方法获取对应的构造器,通过构造器去实例化对象。

获取类的所有信息

1、获取类中的变量(Field)

Field[] getFields():获取类中所有被public修饰的所有变量 Field getField(String
name):根据变量名获取类中的一个变量,该变量必须被public修饰 Field[]
getDeclaredFields():获取类中所有的变量,但无法获取继承下来的变量 Field
getDeclaredField(String name):根据姓名获取类中的某个变量,无法获取继承下来的变量

2、获取类中的方法(Method) 

Method[] getMethods():获取类中被public修饰的所有方法
Method getMethod(String name, Class…<?>
paramTypes):根据名字和参数类型获取对应方法,该方法必须被public修饰
Method[] getDeclaredMethods():获取所有方法,但无法获取继承下来的方法
Method getDeclaredMethod(String name, Class…<?>
paramTypes):根据名字和参数类型获取对应方法,无法获取继承下来的方法

3、获取类的构造器(Constructor) 

Constuctor[] getConstructors():获取类中所有被public修饰的构造器 Constructor
getConstructor(Class…<?> paramTypes):根据参数类型获取类中某个构造器,该构造器必须被public修饰
Constructor[] getDeclaredConstructors():获取类中所有构造器 Constructor
getDeclaredConstructor(class…<?> paramTypes):根据参数类型获取对应的构造器

反射的优缺点 

  • 优点:

能够运行时动态获取类的实例,提高灵活性;

与动态编译结合;

  • 缺点:

使用反射性能较低,需要解析字节码(.class文件),将内存中的对象进行解析;

相对不安全,破坏了封装性(因为通过反射可以获得私有方法和属性);

解决方案:

  1. 通过setAccessible(true)关闭JDK的安全检查来提升反射速度;
  2. 多次创建一个类的实例时,有缓存会快很多;
  3. ReflectASM工具类,通过字节码生成的方式加快反射速度 ;

反射的应用场景 

1、Spring 实例化对象:当程序启动时,Spring 会读取配置文件applicationContext.xml并解析出里面所有的标签实例化到IOC容器中。
2、反射 + 工厂模式:通过反射消除工厂中的多个分支,如果需要生产新的类,无需关注工厂类,工厂类可以应对各种新增的类,反射可以使得程序更加健壮。
3、JDBC连接数据库:使用JDBC连接数据库时,指定连接数据库的驱动类时用到反射加载驱动类


今天的分享就到此为止啦,精彩下期继续哦!😁😁😁

  • 36
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 36
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值