Java的反射机制ヾ(≧▽≦*)o

目录

 反射

反射的概念

反射的优点和缺点 

    优点:

    缺点:

    解决方案:

 Class类 

 Class类的概念

 获取Class对象的三种方法

 反射实例化对象

用方法反射调

反射读写属性 


反射

反射的概念

Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键。

                                                                                                     ——————百度百科

反射是Java语言中的一种机制,通过这种机制可以动态地实例化对象、读写属性、调用方法 

反射的优点和缺点 

优点:

  • 能够运行时动态获取类的实例,提高灵活性;
  • 与动态编译结合;

缺点:

  • 使用反射性能较低,需要解析字节码(.class文件),将内存中的对象进行解析;
  • 相对不安全,破坏了封装性(因为通过反射可以获得私有方法和属性);

解决方案:

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

 Class类 

 Class类的概念

        Class类是一个比较特殊的类,它是反射机制的基础,Class类的对象表示正在运行的Java程序中的类或接口,也就是任何一个类被加载时,即将类的.class文件(字节码文件)读入内存的同时,都自动为之创建一个java.lang.Class对象。Class类没有公共构造方法,其对象是JVM在加载类时通过调用类加载器中的defineClass()方法创建的,因此不能显式地创建一个Class对象。通过这个Class对象,才可以获得该对象的其他信息。

                                                                                             ——————百度百科

获取Class对象的三种方法

这里我会写一个学生类为例子

package com.zking.reflex;

public class Student {
	private String sid;

	private String sname;

	public Integer age;
	
	static{
		System.out.println("加载进jvm中!");
	}

	@Override
	public String toString() {
		return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + "]";
	}

	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")
	private Integer add(Integer a, Integer b) {
		return new Integer(a.intValue() + b.intValue());
	}
}

 ❤获取的方法

大家注意了,这里我们需要填类的权限命名 ,获取命名的方法如下图片所示:

首先点开学生类(例子), 鼠标右键点击绿色的Student,选择Copy Qualified Name,类的权限命名就拿到了。

 Java的反射机制ヾ(≧▽≦*)o_第1张图片

 然后复制到Class.forName(),的括号里就完成了。

package com.zking.reflex;

public class Demo {

	@SuppressWarnings("rawtypes")
	public static void main(String[] args) throws Exception {
		//1.通过 Class.forName(类的权限命名) 获取Class
		Class clazz = (Class)Class.forName("com.zking.reflex.Student");
		
		//2.通过 类.class 获取Class
		Class clazz02 = Student.class;
		
		//3.通过 对象.getClass() 获取Class
		Student stu = new Student();
		Class clazz03 = stu.getClass();
		
		System.out.println(clazz);
		System.out.println(clazz02);
		System.out.println(clazz03);
	}
	
}

运行结果: 

 Java的反射机制ヾ(≧▽≦*)o_第2张图片

 获取的值都是一样的。

 反射实例化对象

还是以学生类为例子

        //通过反射实例化对象
		//1.调用无参构造方法
		Constructor c1 = clazz.getConstructor();
		Student stu01 = c1.newInstance();
		stu01.setSname("纪念品");
		System.out.println(stu01);
		
		//2.调用带一个参数的构造方法
		Constructor c2 = clazz.getConstructor(String.class);
        Student stu02 = c2.newInstance("001");
        stu02.setSname("流浪者");
		System.out.println(stu02);
		
		//3.调用带两个参数的构造方法
		Constructor c3 = clazz.getConstructor(String.class,String.class);
        Student stu03 = c3.newInstance("002","小女巫");
		System.out.println(stu03);
        
		//4.调用私有的方法
		//Declared 可以获取公共的或私有的属性或方法
		Constructor c4 = clazz.getDeclaredConstructor(Integer.class);
        c4.setAccessible(true);
		Student stu04 = c4.newInstance(18);
        System.out.println(stu04);

用方法反射调

            Method method = clazz.getMethod("hello");
			stu04.setSname("lihao");
            //调用方法
			method.invoke(stu04);
			
			Method method02 = clazz.getMethod("hello",String.class);
			method02.invoke(stu04, "zengfanyan");
			
            //获取私有方法
			Method method03 = clazz.getDeclaredMethod("add",Integer.class, Integer.class);
			method03.setAccessible(true);
			int rv = (int)method03.invoke(stu04, 1,1);
			System.out.println(rv);

反射读写属性 

            Field f = clazz.getField("age");
			f.set(stu04, 78);
			System.out.println(stu04);
			System.out.println(f.get(stu04));
			
            //获取私有属性
			Field f01 = clazz.getDeclaredField("sname");
			f01.setAccessible(true);
            //调用属性
			f01.set(stu04, "lihao is hao ren");
			System.out.println(stu04);

补充:
Bean对象

除了上述获取属性的方法之外,还可以通过BeanUtil.getproperty(对象名,“属性”)的方式获取属性,其原理是先调用类中的公开get属性的方法获取再通过反射机制进行获取

 好了,这篇文章就到这里结束了,拜拜!

Java的反射机制ヾ(≧▽≦*)o_第3张图片

你可能感兴趣的:(jvm,大数据,java)