JavaWEB.反射机制(学习笔记)
JavaWEB.反射机制(学习笔记)
黑武士 发表于3年前
JavaWEB.反射机制(学习笔记)
  • 发表于 3年前
  • 阅读 39
  • 收藏 0
  • 点赞 0
  • 评论 0

【腾讯云】如何购买服务器最划算?>>>   

摘要: 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));
 
         
    }
}


标签: 反射
共有 人打赏支持
粉丝 6
博文 13
码字总数 49122
×
黑武士
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: