欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JavaWEB.反射机制(学习笔记)

程序员文章站 2024-01-21 20:31:46
...
/*
反射:反射就是加载类,并解剖出类的各个组成部分(反射的最大用处就是拿来做框架)

反射加载类:
Java中有一个Class类用于代表某一个类的字节码.
Class类既然代表某个类的字节码,它当然就要提供加载某个类
字节码的方法:forName(). forName方法用于加载某个类的字节
码到内存中,并使用class对象进行封装

另外两种得到class对象的方式
类名.class;
对象.getClass();
*/
//Person.java
package cn.cokeer.reflect;
public class Person{
}

//Demo1.java
package cn.cokeer.reflect;
public class Demo1
{
	/*
		反射:加载类演示获得类的字节码
	*/
	public static void main(String[] args) throws ClassNotFoundException
	{
		//1.第一种方式
		Class clazz = Class.forName("cn.cokeer.reflect.Person"); //加载Person的字节码到内存中
		//2.第二种方式
		Class clazz1 = new Persion().getClass();
		//3.第三种方式
		Class clazz2 = Persion.class;
	}
}

/*
Class对象常用方法:
//调用公有的
 Constructor<T> getConstructor(Class<?>... parameterTypes) //返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。 //白话:解剖出这个类里的某一个构造函数
 Method getMethod(String name, Class<?>... parameterTypes)  //返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。 //白话:解剖出这个类里的某一个方法
 Field getField(String name) //返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段. //白话:解剖出这个类里的某一个字段(属性)

//调用私用的
 Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)  //返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。
 Method getDeclaredMethod(String name, Class<?>... parameterTypes)  //返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。
 Field getDeclaredField(String name)  //返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。

 这些方法分别用于解剖出一个类的构造函数,方法,字段(属性)
*/

//利用Constructor创建对象
//Person.java
package cn.cokeer.reflect;

import java.io.InputStream;
import java.util.List;

public class Person{
	public String name = "zhangsan";
	private int password = 123;
	private static int age = 23;
	
	public Person(){
		System.out.println("Person");
	}

	public Person(String name){
		System.out.println("Person name");
	}

	public Person(String name,int password){
		System.out.println("Person name password");
	}

	private Person(List list){
		System.out.println("List");
	}

	public static void main(String[] args)
	{
		System.out.println("Main....");
	}
	
	public void aa1(){
		System.out.println("aa1");
	}

	public void aa1(String name,int password){
		System.out.println(name + ": " + password);
	}

	public Class[] aa1(String name,int[] password){
		return new Class[]{String.class};
	}

	private void aa1(InputStream in){
		System.out.println(in);
	}

	public static void aa1(int num){
		System.out.println(num);
	}
}
//Demo2.java
package cn.cokeer.reflect;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;

import org.junit.Test;
//解剖类的构造函数,创建类的对象
public class Demo2{
	@Test
	//反射无参构造函数 pubilc Person()
	public void test1() throws Exception{
		//第一步,加载类
		Class clazz = Class.forName("cn.cokeer.reflect.Person");
		Constructor c = clazz.getConstructor(null); //null表示要解剖无参的构造函数
		Person p = (Person)c.newInstance(null); //创建对象,不传参数,它是作为Object返回,所以我们要做强转
		System.out.println(p.name);
	}
	@Test
	//反射有参的构造函数 public Person(String name)
	public void test2() throws Exception{
		Class clazz = Class.forName("cn.cokeer.reflect.Person");
		Constructor c = clazz.getConstructor(String.class); //这里要以参数类型来区分反射哪一个构造函数
		Person p = (Person)c.newInstance("zhangshan"); //传递参数,这里参数是String类型的,所以传字符串
		System.out.println(p.name);
	}
	@Test
	//反射有参的构造函数 public Person(String name,int password)
	public void test3()throws Exception {
		Class clazz = Class.forName("cn.cokeer.reflect.Person");
		Constructor c = clazz.getConstructor(String.class,int.class); //第一个参数是String,第二个参数是int
		Person p = (Person)c.newInstance("lisi",20);
		System.out.println(p.name);
	}
	@Test
	//反射私有的构造函数 private Person(List list)
	//私有类不可以被外界访问,但是反射可以做到这一点setAccessible(true)
	public void test4() throws Exception{
		Class clazz = Class.forName("cn.cokeer.reflect.Person");
		Constructor c = clazz.getDeclaredConstructor(List.class); //解剖构造函数
		c.setAccessible(true); //暴利反射,这个时候就可以访问private了
		Person p = (Person)c.newInstance(new ArrayList());
		System.out.println(p.name);
	}
/*
多学一招:Sun公司为了简化开发人员创建对象,它在class对象中也提供了一个newInstance方法,用于创建类的对象,这样开发人员可以避免每次都需要去放反射Constructor类以创建对象
不过需要注意的是:class.newInstance方法内部是反射类的无参构造函数创建的对象,所以利用此方法创建类对象时,类必须有一个无参的构造函数
*/
	@Test
	//创建对象的另外一种途径,它等效于test1
	public void test5() throws Exception{
		Class clazz = Class.forName("cn.cokeer.reflect.Person");
		Person p = (Person)clazz.newInstance(); //它只能反射无参的构造函数
		System.out.println(p);
	}
}


/*
反射类的方法:
利用Method类执行方法
*/
//Demo3.java
package cn.cokeer.reflect;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Method;

import org.junit.Test;
//反射类的方法
public class Demo3{
	@Test
	//反射Person类的public void aa1()方法
	public void test1() throws Exception {
		
/*		Class clazz = Class.forName("cn.cokeer.reflect.Person");
		Method method = clazz.getMethod("aa1",null); //第一个参数指定反射哪个方法,第二个参数指定参数类型,无参就写null,这里接受的是可变参数
		Person p = new Person();//因为Class clazz = 	Class.forName("cn.cokeer.reflect.Person");只拿到了Class字节码,但是还没有拿到Person对象,所以这里我们要创建Person对象
		method.invoke(p,null); //上面创建了对象才能调用该对象的方法,参数为null
*/		
		Class clazz = Class.forName("cn.cokeer.reflect.Person");
		Method method = clazz.getMethod("aa1", null);
		method.invoke(new Person(),null);
	}
	@Test
	//反射public void aa1(String name,int password)
	public void test2() throws Exception {
		Class clazz = Class.forName("cn.cokeer.reflect.Person");
		Method method = clazz.getMethod("aa1",String.class,int.class);
		method.invoke(new Person(),"zhangshan",23);
	}
	//反射public Class[] aa1(String name,int[] password)
	@Test
	public void test3() throws Exception {
		Class clazz = Class.forName("cn.cokeer.reflect.Person");
		Method method = clazz.getMethod("aa1", String.class,int[].class);
		Class cs[] = (Class[])method.invoke(new Person(), "cokeer",new int[]{1,2,3});
		System.out.println(cs[0]);
		
	}
	//反射private void aa1(InputStream in)
	@Test
	public void test4() throws Exception{
		Class clazz = Class.forName("cn.cokeer.reflect.Person");
		Method method = clazz.getDeclaredMethod("aa1", InputStream.class); //得到私有类型的
		method.setAccessible(true); //打开访问权限	
		method.invoke(new Person(),new FileInputStream("C:/Users/Administrator/Desktop/1.txt"));
	}
	//反射public static void aa1(int num)
	@Test
	public void test5() throws Exception {
		Class clazz = Class.forName("cn.cokeer.reflect.Person");
		Method method = clazz.getMethod("aa1", int.class);
		method.invoke(null, 32); //静态方法在调用时不需要对象,所以obj参数为null
	}
	//反射Main方法public static void main(String[] args)
	@Test
	public void test6() throws Exception {
		Class clazz = Class.forName("cn.cokeer.reflect.Person");
		Method method = clazz.getMethod("main", String[].class);
		//method.invoke(null, new String[]{"a","b","c"}); //main(String s1,String s2,String s3)由于JDK升级造成的问题,默认会把我们传递的数组当成参数来执行
		//所以为了解决以上问题,我们可以这样来做
		//method.invoke(null, new Object[]{new String[]{"a","b","c"}});
		//也可以这样做
		method.invoke(null, (Object)new String[]{"a","b","c"}); //这样可以欺骗JVM虚拟机,让它不认为这个是数组,它就不会拆分它了
	}
}

/*
反射类的属性:
*/
package cn.cokeer.reflect;

import java.lang.reflect.Field;

import org.junit.Test;

/**
 * 反射属性(字段),反射字段无非就是想向里面装入数据,或读取数据
 * @author Administrator
 *
 */
public class Demo4 {
	//反射获取public String name = "Test";
	@Test
	public void test1() throws Exception {
		Class clazz = Class.forName("cn.cokeer.reflect.Person");
		Object obj = clazz.newInstance();
		Field f = clazz.getField("name");
		System.out.println(f.get(obj));
	}
	//反射获取private int password;
	@Test
	public void test2() throws Exception {
		Class clazz = Class.forName("cn.cokeer.reflect.Person");
		Object obj = clazz.newInstance();
		Field f = clazz.getDeclaredField("password"); //获取私有属性
		f.setAccessible(true); //打开访问权限
		System.out.println(f.get(obj));
		
		//一般如果不知道属性类型那么可以用getType()方法来判断一下
		/*
		Object value = f.get(new Person());
		Class type = f.getType();
		if(type.equals(String.class)){
			String svalue = (String)value;
			System.out.println(svalue);
		}
		*/
	}
	//反射获取private static int age;
	@Test
	public void test3() throws Exception {
		Class clazz = Class.forName("cn.cokeer.reflect.Person");
		Field f = clazz.getDeclaredField("age");
		f.setAccessible(true);
		System.out.println(f.get(null)); //因为是静态属性,说以不需要给对象
		
	}
	//反射设置属性private int password = 123123;
	@Test
	public void settest2() throws Exception {
		Class clazz = Class.forName("cn.cokeer.reflect.Person");
		Object obj = clazz.newInstance();
		Field f = clazz.getDeclaredField("password"); //获取私有属性
		f.setAccessible(true);
		f.set(obj,123123); //设置属性
		System.out.println(f.get(obj));

		
	}
}


转载于:https://my.oschina.net/kissbaby/blog/369479