java——反射机制初级应用

反射,一种计算机处理方式。是程序可以访问、检测和修改它本身状态或行为的一种能力(百度百科)。
在很多时候我们示例话对象的时候是通过一个关键字new来实现的,并对类的成员进行操作。而反射是通过一个特殊的类的类型来实现我们要对一个类的所有操作.
实例化一个Class类对象方法:
• public static Class<?> forName(String className)
【该方法的前提是知道一个类的全名(包名.类名)】
•public final Class<?> getClass()
【该方法可以获取类的Class类型的对象,但是前提是要先实例化类的本类对象,之后使用本类对象的getClass()方法获取】
•直接使用“类名称.class”
示例:

/-/工具类,上下文会用到:

package com.zhaoqiang.reflex;

public class Person {
    private String name;
    private int age;
    
    public Person(){}
    
    public Person(String name){
        this.name = name;
    }
    
    public Person(String name, int age){
        this.name = name;
        this.age = age;
    }
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    
    public void say(){
        System.out.println("我是中国人,我说中文");
    }
    
    public void say(String str){
        System.out.println("狗娃是楚国人,它会背楚辞");
    }
    
    private void eat(){
        System.out.println("北方吃面条,南方吃米饭,西红柿放盐");
    }
    
}

package com.zhaoqiang.reflex;

import java.util.Date;

public class Demo1 {

    public static void main(String[] args) {
        
        //第一种: 实例化一个本类对象
        Date date = new Date();
        Class<?> cls1 = date.getClass();
    
      // Person类是自己定义的类
    
        // 第二种:获取类的全名(虚拟路径:包名.类名)
        // 此方法会抛出一个异常ClassNotFoundException
        try {
            Class<?> cls2 = Class.forName("/com.zhaoqiang.reflex.Person");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        // 第三种:通过类名实例化一个Class对象
        Class<?> cls3 = Person.class;
        
    }

}

创建了Class类对象我们就可以通过Class类对象来创建一个本类对象。
•public T newInstance() throws InstantiationException,
示例:

package com.zhaoqiang.reflex;

import java.util.Date;

public class Demo1 {

    public static void main(String[] args) throws Exception {
        
        //第一种: 实例化一个本类对象
//      Date date = new Date();
//      Class<?> cls1 = date.getClass();
        
        // 第二种:获取类的全名(虚拟路径:包名.类名)
        // 此方法会抛出一个异常ClassNotFoundException
        try {
            Class<?> cls2 = Class.forName("com.zhaoqiang.reflex.Person");
            
            // 通过Class对象实例化Person对象
            Person per = (Person)cls2.newInstance();
            System.out.println(per.toString());
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        // 第三种:通过类名实例化一个Class对象
//      Class<?> cls3 = Person.class;
        
        
        // 通过Class对象创建一个本类对象
        
        
    }

}

下面是一个简单工厂类使用反射来实现。
示例:

package com.zhaoqiang.reflex;

interface Comput{
    public abstract void say();
}

class HS implements Comput{
    @Override
    public void say() {
        System.out.println("正在使用hs电脑");
    }
}

class DE implements Comput{
    @Override
    public void say() {
        System.out.println("正在使用de电脑");
    }
}


class Factory{
    public static Comput getInstance(String className){
        
        try {
            Class<?> cls = Class.forName(className);
            return (Comput) cls.newInstance();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        
        return null;
    }
}

public class Demo2 {
    public static void main(String[] args) {
        Comput cp = Factory.getInstance("com.zhaoqiang.reflex.HS");
        cp.say();
    }
}

通过Class对象实例化了类对象,一个类对象可能有很多个构造方法,如果类中没有默认构造函数,那么使用上的方法实例化对象就会报错。下面是通过Class对象获取类的构造函数方法:
•public Constructor<T> getConstructor(Class<?>... parameterTypes)
【获取指定的构造方法】

•public Constructor<?> [] getConstructors() throws SecurityException
【获取所有的构造方法】
示例:

package com.zhaoqiang.reflex;

import java.lang.reflect.Constructor;

public class Demo3 {
    public static void main(String[] args) throws Exception {
        Class<?> cls = Person.class;
        
        // 获取一个无参的构造方法
        Constructor<?> cons = cls.getConstructor();
        
        // 获取指定的构造函数
        Constructor<?> cons2 = cls.getConstructor(String.class);
        Person per1 = (Person)cons2.newInstance("张三");
        
        // 获取两个参数的指定构造函数
        Constructor<?> cons3 = cls.getConstructor(String.class,int.class);
        Person per2 = (Person)cons3.newInstance("李四",18);
        
        
        // 获取所有的构造方法
        Constructor<?> consarray[] = cls.getConstructors();
        
        // 特别注意:所有获取的构造方法排序是从构造方法中参多的排在第一个
    }
}

通过反射调用类中普通方法:
•public Method getMethod(String name,Class<?>... parameterTypes)
【获取指定参数的普通方法,第一个参数是方法名称,参数列表的Class类类型】

•public Method[] getMethods() throws SecurityException
【获取所有的普通方法】

这里出现了一个新的类:Mehtod类,该类专门对象普通方法进行操作,要执行普通方法则需要该类中的一个方法:
•public Object invoke(Object obj, Object... args)
【执行该方法,第一个参数是对象的名称,第二个参数是方法中传递的参数】
示例:

package com.zhaoqiang.reflex;

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

public class Demo4 {
    public static void main(String[] args) throws Exception {
        Class<?> cls = Person.class;
        
        Constructor<?> con = cls.getConstructor(String.class,int.class);
        
        Person per = (Person) con.newInstance("狗娃",16);
        
        
        // 无参
        Method mt = cls.getMethod("say");
        mt.invoke(per);
        
        // 有参
        Method mt2 = cls.getMethod("say", String.class);
        mt2.invoke(per, "狗娃");
        
          // 获取所有的方法
        Method[] mt3 = cls.getMethods();
    }
}

通过反射调用类中成员变量:
•public Field getDeclaredField(String name)
【获取指定的属性】

  •public Field[] getDeclaredFields() throws SecurityException
【获取所有的属性】

在上面的方法中又出现了一个新的类 Field,该类是专门对属性进行操作的,在该了中又提供了两个方法
|- public String getName()【获取属性的名称】
|- public Object get(Object obj)【获取属性对应的值】
|- public void set(Object obj, Object value)【为属性设置值】
示例:

package com.zhaoqiang.reflex;

import java.lang.reflect.Field;

public class Demo5 {

    public static void main(String[] args) throws Exception {
        Class<?> cls = Person.class;
        Person per = (Person) cls.newInstance();
        
        // 获取指定的属性
        Field f = cls.getDeclaredField("name");
        
        // 获取所有的属性
        Field[] farray = cls.getDeclaredFields();
        
        // 获取属性名称
        farray[0].getName();
        
        
        // 取消private封装
        f.setAccessible(true);
        
        // 设置值
        f.set(per, "狗娃");
        
        // 获取属性对于的值
        farray[0].get(per);
        
        System.out.println(per.getName());
    }

}

java反射的一些简单应用:
示例一:

package com.zhaoqiang.reflex;

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

/*
 * 要求将Person 对象中的属性以及属性值转换成一个指定字符串格式:
 * "person":"{"name":"smith","age":"123"}"
 * */

public class Test1 {

    public static void main(String[] args) throws Exception {
        // 获取Class对象
        Class<?> cls = Person.class;
        
        // 获取两个参数的构造函数
        Constructor<?> con = cls.getConstructor(String.class,int.class);
        
        // 实例化一个Person对象
        Person per = (Person) con.newInstance("狗娃",100);
        
        // 获取Person类中所有属性
        Field[] f = cls.getDeclaredFields();
        
        // 声明一个StringBuffer对象
        StringBuffer sb = new StringBuffer();
        sb.append("\"Person\":\"{\"");
        
        for(int i=0; i<f.length; i++){
            
            // 解除封装
            f[i].setAccessible(true);
            sb.append("\""+f[i].getName()+"\":");
            sb.append("\""+f[i].get(per)+"\"");
        }
        sb.delete(sb.length()-1, sb.length());
        sb.append("};");
        System.out.println(sb);
        
    }

}

package com.zhaoqiang.reflex;

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

/*
 * 要求将Person 对象中的属性以及属性值转换成一个指定字符串格式:
 * "person":"{"name":"smith","age":"123"}"
 * */

public class Test1 {

    public static void main(String[] args) throws Exception {
        // 获取Class对象
        Class<?> cls = Person.class;
        
        // 获取两个参数的构造函数
        Constructor<?> con = cls.getConstructor(String.class,int.class);
        
        // 实例化一个Person对象
        Person per = (Person) con.newInstance("狗娃",100);
        
        // 获取Person类中所有属性
        Field[] f = cls.getDeclaredFields();
        
        // 声明一个StringBuffer对象
        StringBuffer sb = new StringBuffer();
        sb.append("\"Person\":\"{\"");
        
        for(int i=0; i<f.length; i++){
            
            // 解除封装
//          f[i].setAccessible(true);
            // 不解除封装,通过方法名获取数据
            Method mt = cls.getMethod(initCap(f[i].getName())); // 去的属性对应的get方法
            
            sb.append("\""+f[i].getName()+"\":");
//          sb.append("\""+f[i].get(per)+"\"");
            sb.append("\""+mt.invoke(per)+"\"");
        }
        sb.delete(sb.length()-1, sb.length());
        sb.append("};");
        System.out.println(sb);
        
    }
    
    public static String initCap(String name){
        return "get"+name.substring(0,1).toUpperCase()+name.substring(1);
    }

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容