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

/*
反射:反射就是加载类,并解剖出类的各个组成部分(反射的最大用处就是拿来做框架)

反射加载类:
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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值