二刷java基础第二十二天——反射

Posted 名字真的很急用

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二刷java基础第二十二天——反射相关的知识,希望对你有一定的参考价值。

一:什么是反射?

  • 利用代码区中的数据(class),去创建对象;而不需要去new
    • 构造方法
    • 成员变量
    • 成员方法
  • 在代码区存储的class并不是真正的class文件(物理),而是一个虚拟的对象(Class)

二:Class

  • 管理class文件对象

  • 获取class文件对象的三种方式

  • 方式一:通过Object类中的getClass()方法 
    方式二:类名.class获取到字节码文件对象(任意的数据类型,都默认具有静态的class属性)
    方式三:forName("全路径")
    
  public class 反射 {

	public static void main(String[] args) throws ClassNotFoundException {
		// TODO Auto-generated method stub

		
		//代码区中的都是运行时状态
		
		  //获取class文件对象的三种方式

		  // 方式一:通过Object类中的getClass()方法 
		   //方式二:类名.class获取到字节码文件对象(任意的数据类型,都默认具有静态的class属性)
		   //方式三:forName("全路径")
		   
		Person p = new Person();
		
		Class  a= p.getClass();
		System.out.println(a);
		
		Class b =Person.class;
		System.out.println(b);
		
		Class c =Class.forName("BJday29.Person"); //要写全路径
		System.out.println(c);

		
		//Class内部结构
		//构造方法
		//成员方法
		//成员变量
	}

}

class Person{
	
}

三:class文件的内部成员

  • 构造方法:Constructor
  • 成员方法: Method
  • 成员变量: Filed

四:获取构造方法

Constructor<T> getConstructor(<?>... parameterTypes) 
返回一个 Constructor对象,该对象反映 Constructor对象表示的类的指定的公共 类函数。  
Constructor<?>[] getConstructors() 
返回包含一个数组 Constructor对象反射由此表示的类的所有公共构造 类对象。
====================================================================
Constructor<T> getDeclaredConstructor(<?>... parameterTypes) 
返回一个 Constructor对象,该对象反映 Constructor对象表示的类或接口的指定 类函数。  
Constructor<?>[] getDeclaredConstructors() 
返回一个反映 Constructor对象表示的类声明的所有 Constructor对象的数组 类 。  


  • 利用构造方法创建实例,类似new对象。

    • newInstance(Object... initargs)  //可变参,参数可以为0,1个或2个,几个....
      
package BJday29;

import java.lang.reflect.Constructor;

public class 反射的成员 {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub

		
		Class<?> c =Class.forName("BJday29.Student");
		
		//利用该对象获取公共的所有的构造方法
		Constructor<?>[] constructors = c.getConstructors();
		
		//返回一个反映 Constructor对象表示的类声明的所有 Constructor对象的数组 类 。 
		//Constructor<?>[] declaredConstructor = c.getDeclaredConstructors();
		
		
//		for(Constructor s:constructors) {
//			System.out.println(s);
//		}
		//获取指定的构造方法
		//getConstructor(类<?>... parameterTypes) 
		//返回一个 Constructor对象,该对象反映 Constructor对象表示的类的指定的公共 类函数。
		//Constructor<?> constructor = c.getConstructor(String.class,int.class);
		
		
		//getDeclaredConstructor(类<?>... parameterTypes) 
		//返回一个 Constructor对象,该对象反映 Constructor对象表示的类或接口的指定 类函数。
		
		   // Constructor<?> declaredConstructor = c.getDeclaredConstructor(String.class);
		    
		//newInstance() 
		//创建由此 类对象表示的类的新实例。
		//Constructor<?> constructor = c.getConstructor(int.class); //获得公共的无参构造方法
	    //Student s = (Student)constructor.newInstance(1);
		// System.out.println(s);   
		 
		//能否获得私有的构造方法并创建对象
		//Constructor<?> declaredConstructor = c.getDeclaredConstructor(String.class);
		//Student s = (Student)declaredConstructor.newInstance("tom");
		//System.out.println(s);   //会报错  因为安全检查机制  ,所有要想实现 ,我们需要解除这个安全机制,
		
		Constructor<?> declaredConstructor = c.getDeclaredConstructor(String.class);
		        declaredConstructor.setAccessible(true);//我们需要解除这个安全机制,暴力破解
				Student s = (Student)declaredConstructor.newInstance("tom");
				System.out.println(s);
	}

}


class Student {
	public int age;
	public String sex;
	Object obj = new Object();
	protected double sum;
	private int a;
	private String name;
	public Student() {
		System.out.println("公开空参");
	}
	
//	public Student(int a) {
//		this.a=a;
//		System.out.println("公开的有参");
//	}
	
	private Student(String name) {
		this.name=name;
		System.out.println("私有空参");
	}
	
	public Student(String name,int a) {
		System.out.println("私有的有参");
	}

	@Override
	public String toString() {
		return "Student [a=" + a + ", name=" + name + "]";
	}
	
	//成员方法
	public String getName() {
		return name;
	}

	public void setName(String name) {
		 this.name=name;
	}

	private int getA() {
		return a;
	}

	private void setA(int a) {
		this.a = a;
	}
	}

五:获取成员变量

  • Field getDeclaredField(String name) 
    返回一个 Field对象,它反映此表示的类或接口的指定已声明字段 类对象。  
    Field[] getDeclaredFields() 
    返回的数组 Field对象反映此表示的类或接口声明的所有字段 类对象 
    =============================================================
    Field getField(String name) 
    返回一个 Field对象,它反映此表示的类或接口的指定公共成员字段 类对象。  
    Field[] getFields() 
    返回包含一个数组 Field对象反射由此表示的类或接口的所有可访问的公共字段 类对象。  
    
    
  • 利用反射,给成员变量赋值

set(Object obj,  Object value)
- obj:要将该字段绑定在某个对象上
- 给字段赋值 
package BJday29;

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

public class 反射的成员变量 {

	public static void main(String[] args) throws Exception   {
		// TODO Auto-generated method stub
		Class<?> c =Class.forName("BJday29.Student");
		
		
		//Field getField(String name) 
		//返回一个 Field对象,它反映此表示的类或接口的指定公共成员字段 类对象。  
		//Field[] getFields() 
		//返回包含一个数组 Field对象反射由此表示的类或接口的所有可访问的公共字段 类对象。 

		//Field getDeclaredField(String name) 
		//返回一个 Field对象,它反映此表示的类或接口的指定已声明字段 类对象。  
		//Field[] getDeclaredFields() 
		//返回的数组 Field对象反映此表示的类或接口声明的所有字段 类对象。 

//		Field[] fields = c.getFields();  //获取所有公共的变量
//		for(Field f:fields) {
//			System.out.println(f);
//		}
		//获取所有的变量
//		Field[] fields2 = c.getDeclaredFields();
//		for(Field f:fields2) {
//			System.out.println(f);
//		}
		
		//获取指定的变量
		Field field3 = c.getDeclaredField("obj");
		//System.out.println(field3);
		
		Field field4 = c.getDeclaredField("age");
		//System.out.println(field4);
		
		//获取构造方法 为对象设置属性值
		Constructor<?> declaredConstructor = c.getDeclaredConstructor(String.class);
		 declaredConstructor.setAccessible(true);//我们需要解除这个安全机制,暴力破解
		Student s = (Student)declaredConstructor.newInstance("tom");
		//获取指定的公开成员变量
		
		Field sex =c.getDeclaredField("name");
		sex.setAccessible(true);
		//set(Object obj, Object value) 
		//将指定对象参数上的此 Field对象表示的字段设置为指定的新值。
	    sex.set(s, "man"); //会把构造函数的赋值给覆盖
         System.out.println(s);
	}

}

六:成员方法

方法 getMethod(String name, 类<?>... parameterTypes) 
返回一个 方法对象,它反映此表示的类或接口的指定公共成员方法 类对象。  
方法[] getMethods() 
返回包含一个数组 方法对象反射由此表示的类或接口的所有公共方法 类对象,包括那些由类或接口和那些从超类和超接口继承的声明。  
============================================================
getDeclaredMethod(String name, 类<?>... parameterTypes) 
返回一个 方法对象,它反映此表示的类或接口的指定声明的方法 类对象。  
方法[] getDeclaredMethods() 
返回包含一个数组 方法对象反射的类或接口的所有声明的方法,通过此表示 类对象,包括公共,保护,默认(包)访问和私有方法,但不包括继承的方法。  

package BJday29;

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

public class 反射成员方法 {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub

		Class<?> c =Class.forName("BJday29.Student");
		
		//方法 getDeclaredMethod(String name, 类<?>... parameterTypes) 
		//返回一个 方法对象,它反映此表示的类或接口的指定声明的方法 类对象。  
		//方法[] getDeclaredMethods() 
		//返回包含一个数组 方法对象反射的类或接口的所有声明的方法,通过此表示 类对象,包括公共,保护,默认(包)访问和私有方法,但不包括继承的方法。 

		//方法 getMethod(String name, 类<?>... parameterTypes) 
		//返回一个 方法对象,它反映此表示的类或接口的指定公共成员方法 类对象。  
		//方法[] getMethods() 
		//返回包含一个数组 方法对象反射由此表示的类或接口的所有公共方法 类对象,包括那些由类或接口和那些从超类和超接口继承的声明。 

		
		//invoke(Object obj, Object... args) 
		//在具有指定参数的 方法对象上调用此 方法对象表示的底层方法。
		
		Constructor<?> declaredConstructor = c.getDeclaredConstructor(String.class);
		 declaredConstructor.setAccessible(true);//我们需要解除这个安全机制,暴力破解
		Student s = (Student)declaredConstructor.newInstance("jack");
		
		//Method[] methods = c.getMethods();
		
		//Method method = c.getMethod("setName", String.class);
		
		//Method[] methods2 = c.getDeclaredMethods();
		
		Method method2 = c.getDeclaredMethod("setA", int.class);
		method2.setAccessible(true);
		
		Field sex =c.getDeclaredField("name");
		sex.setAccessible(true);
		sex.set(s, "man");
		 
		method2.invoke(s, 100);
		System.out.println(s);
	}

}

七:练习题

  • 泛型擦除

    • package 泛型擦除;
      
      import java.lang.reflect.Method;
      import java.util.ArrayList;
      
      public class Demo {
          public static void main(String[] args) throws Exception{
              ArrayList<Integer> list = new ArrayList();
              list.add(1);
              list.add(200);
             // list.add("abc");
              Class<?> aClass = Class.forName("java.util.ArrayList");
              Method add = aClass.getMethod("add", Object.class);
              //暴力破解
              add.setAccessible(true);
              //将该方法和对象进行绑定
              add.invoke(list,"哈哈");
      
              System.out.println(list);
          }
      }
      
      

以上是关于二刷java基础第二十二天——反射的主要内容,如果未能解决你的问题,请参考以下文章

javaSE第二十二天

Mysql基础第二十二天,插入数据

(89)Wangdao.com第二十二天_JavaScript DocumentFragment 节点

java基础第二十三天——解析XML文件和DTD约束

linux基础学习第二十二天之AWK详解

Python 基础第二十三天(反射)