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