基于java中反射的总结分析

刚开始学习java的时候真的很难理解反射到底是个什么东西

一些书籍,哪怕是很经典的书籍都解释的让人感觉懵懵的,或许的确是我太笨

况且,网上说在将来学习框架的时候需要经常应用到反射机制,这样一来总让人心里有些不安

就方才偶然又把讲解反射的章节和视频看了一点,觉得能理解一些了

现在决定一鼓作气,边看边写,顺便把一些主要的内容和操作都记载到这里

我想,对于我这么一个笨笨的人来说,学习的最好方法也许就是不断重复

遇到不懂的知识就停下来把以往的重新学一遍,虽然浪费了很多时间,但对我也有些效果

我的理解是:所谓反射,就是根据一个已经实例化了的对象来还原类的完整信息

至少对我而言,我认为它带给我的好处是,让我从下往上的又了解了一遍面向对象

x_x 在此又痛恨一边那些厚部头们,把我的脑细胞搞死一片

Class类

如果要完成反射,那么必须了解Class类

实例1:通过对象取得包名和类名


代码如下:

package org.siu;

class Test {

}

public class Demo {
    public static void main(String[] args) {
        Test t = new Test();
        System.out.println(t.getClass());
        System.out.println(t.getClass().getName());
    }
}

编译结果如下,注意包的编译方式即可

此处的getClass()方法是默认继承自Object类的

在java中,Object类是所有类的父类,同样,所有类的实例化对象也都是Class类的实例

因此,这样一来就会牵扯到向上转型和向下转型的概念

由于向下转型的不安全因素,在这里泛型也会接踵而来

(不过我想说的是,此处的泛型设计很刺眼!尼玛,整个java的语法设计同样刺眼,超恶心!!!)

实例2:Class类的实例化

由于Class类没有构造方法,所以实例化Class类的方式有点特殊,有三种方式:

对象.getClass( )
类.Class
forName( )


代码如下:

class Test {

}

public class Demo {
    public static void main(String[] args) {
        //方式一:
        Test t = new Test();
        Class<? extends Test> c1 = t.getClass();
        System.out.println(c1);

//方式二:
        //为了避免特殊性,这里不用Test类,而用java库中的String类
        Class<String> c2 = String.class;
        System.out.println(c2);

//方式三:
        //forName()方法会抛出异常
        Class<?> c3 = null;
        try {
            c3 = Class.forName("Test");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println(c3);
    }
}

其中,forName( )方法需要重点掌握,因为它可以在类不确定的情况下实例化Class,更具灵活性

Class类的应用

Class类中有一个方法叫做newInstance( ),它可以用来创建一个Class类对象的新实例

怎么说呢?Class对象包含的内容就是反射好的那个类,我们要构造那个类的新实例(新对象)

实例3:Class类的无参构造对象


代码如下:

public class Demo {
    public static void main(String[] args) {
        //实例化Class对象,forName()方法会抛异常
        Class<?> c = null;
        try {
            //这里需要完整的包名和类名
            c = Class.forName("java.lang.String");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

//生成一个字符串的引用
        String s = null;
        try {
            //将构造好的对象向下转型为String类
            //newInstance()方法会抛异常
            s = (String) c.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        System.out.println("字符串长度: " + s.length());
    }
}

这样就通过无参数的形式构造了一个新的对象,如同正常模式中

通过无参构造方法来构造新对象一样

我们知道,类中除了有无参构造方法,还会存在有参数的构造方法

那在反射中如何通过有参数的形式构造对象呢?接着看

实例4:Class类的有参构造对象


代码如下:

import java.lang.reflect.Constructor;

public class Demo {
    //下面的几个方法抛出来的异常太多,为了代码的紧凑性,这里就直接抛给虚拟机了
    public static void main(String[] args) throws Exception {
        Class<?> c = null;
        try {
            c = Class.forName("java.lang.String");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        char[] ch = {'h','e','l','l','o'};
        String s = null;
        //获得Class类对象的有参构造方法,括号里面参数的写法是:类型.class
        Constructor<?> con = c.getConstructor(char[].class);
        //用此构造方法构造一个新的字符串对象,参数为一个char数组
        s = (String) con.newInstance(ch);
        System.out.println("构造的字符串:" + s);
    }
}

我们还是使用String类做例,因为String类用的比较多,便于理解

这里需要注意的是,构造方法需要使用getConstructor( )方法获得

至于参数类型则是:原有类型.class

还有一点,无论是有参还是无参,这里所使用的构造方法,原本的类里面必须对应存在

那么,如何才能知道原有类里面的构造方法,普通方法,继承的父类等详细信息呢?接着看

获取类的结构

要通过反射获取类的结构我们这里要导入一个新的包java.lang.reflect

实例5:取得类的构造方法


代码如下:

import java.lang.reflect.Constructor;
import java.util.Arrays;

public class Demo {
    //下面的几个方法抛出来的异常太多,为了代码的紧凑性,这里就直接抛给虚拟机了
    public static void main(String[] args) throws Exception {
        Class<?> c = null;
        try {
            c = Class.forName("java.lang.Boolean");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //这里的getConstructors()方法返回的是一个Constructor数组
        Constructor<?>[] cons = c.getConstructors();
        //打印的方式你可以自己写,为了方便我用Arrays.toString(),凑合着看
        System.out.println(Arrays.toString(cons));
    }
}

我选择了Boolean类来做例,因为Boolean类的构造方法就两个,方便看

实例6:取得类所实现的接口


代码如下:

import java.util.Arrays;

public class Demo {
    public static void main(String[] args) throws Exception {
        Class<?> c = null;
        try {
            c = Class.forName("java.lang.Boolean");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Class<?>[] in = c.getInterfaces();
        System.out.println(Arrays.toString(in));
    }
}

没什么好说的,看结果

实例7:取得父类


代码如下:

public class Demo {
    public static void main(String[] args) throws Exception {
        Class<?> c = null;
        try {
            c = Class.forName("java.lang.Boolean");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //注意了,这里不会是数组,why?
        Class<?> su = c.getSuperclass();
        System.out.println(su);
    }
}

别忘了,java中是单继承,父类只有一个

实例8:取得类的全部方法


代码如下:

import java.lang.reflect.Method;

public class Demo {
    public static void main(String[] args) throws Exception {
        Class<?> c = null;
        try {
            c = Class.forName("java.lang.Boolean");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Method[] m = c.getMethods();
        //好吧,这次我就大发慈悲的写个打印列表出来
        for (int i = 0; i < m.length; i++) {
            System.out.println(m[i]);
        }
    }
}

截取一部分,看看,意思下就行了……这几个例子都比较简单

实例9:取得本类的全部属性


代码如下:

import java.lang.reflect.Field;

class Person {
    private String name;
    private int age;
}

public class Demo {
    public static void main(String[] args) throws Exception {
        Class<?> c = null;
        try {
            c = Class.forName("Person");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Field[] f = c.getDeclaredFields();
        for (int i = 0; i < f.length; i++) {
            System.out.println(f[i]);
        }
    }
}

getDeclaredFielsd()方法可以获取全部属性,getFields()只能获取公共属性

实例10:获取本类中属性的值


代码如下:

import java.lang.reflect.Field;

class Person {
    public String name;
    private int age;

public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

public class Demo {
    public static void main(String[] args) throws Exception {
        Person p = new Person("zhangsan",12);

Class<?> c = p.getClass();

//获取公共属性的值
        Field f1 = c.getField("name");
        //get(p)表明要获取是哪个对象的值
        String str = (String) f1.get(p);
        System.out.println("姓名: " + str);

//获取私有属性的值
        Field f2 = c.getDeclaredField("age");
        //age是私有属性,所以要设置安全检查为true
        f2.setAccessible(true);
        int age = (int) f2.get(p);
        System.out.println("年龄: " + age);
    }
}

要注意的是:setAccessible()方法可以设置是否访问和修改私有属性

坦白说,java学到现在我还没发现什么能亮瞎我钛金眼的知识在里边

每次都是写一堆繁琐的语法实现个小玩意儿,不然就是拼命调用API,拼命的抛异常

让本身显得不够紧凑的代码变得愈发累赘

如果我喜欢一门语言,在我利用它做出东西来之前,它本身的特性必须能够打动我

显然,java并不让我快乐,也许很多程序员跟我一样是被迫使用java的

仅以此来安抚我那颗孤独编码的心,下面接着看内容

反射的应用实例11:通过反射修改属性


代码如下:

import java.lang.reflect.Field;

class Person {
    private String name;

public Person(String name) {
        this.name = name;
    }

public String toString() {
        return "姓名: " + this.name;
    }
}

public class Demo {
    public static void main(String[] args) throws Exception {
        Person p = new Person("王二狗");
        System.out.println(p);
        Class<?> c = p.getClass();

//定义要修改的属性
        Field f = c.getDeclaredField("name");
        f.setAccessible(true);
        //修改属性,传入要设置的对象和值
        f.set(p, "张二蛋");
        System.out.println(p);
    }
}

几个方法都是有联系的,如果看不懂就先熟悉上面几个例子

实例12:通过反射调用方法


代码如下:

import java.lang.reflect.Method;

class Person {
    public void print(int i) {
        System.out.println("我在写数字: " + i);
    }

public static void say(String str) {
        System.out.println("我在说: " + str);
    }
}

public class Demo {
    public static void main(String[] args) throws Exception {
        Person p = new Person();
        Class<?> c = p.getClass();

//getMethod()方法需要传入方法名,和参数类型
        Method m1 = c.getMethod("print", int.class);
        //invoke()表示调用的意思,需要传入对象和参数
        m1.invoke(p, 10);

Method m2 = c.getMethod("say", String.class);
        //这里的null表示不由对象调用,也就是静态方法
        m2.invoke(null, "你妹");
    }
}

这里演示了一个普通的有参方法和一个静态方法

既然有参数的都写出来了,那么无参的就更简单了,直接传入一个对象即可

实例13:通过反射操作数组


代码如下:

import java.lang.reflect.Array;

public class Demo {
    public static void main(String[] args) throws Exception {
        int[] arr = {1,2,3,4,5};
        Class<?> c = arr.getClass().getComponentType();

System.out.println("数组类型: " + c.getName());
        int len = Array.getLength(arr);
        System.out.println("数组长度: " + len);
        System.out.print("遍历数组: ");
        for (int i = 0; i < len; i++) {
            System.out.print(Array.get(arr, i) + " ");
        }
        System.out.println();
        //修改数组
        System.out.println("修改前的第一个元素: " + Array.get(arr, 0));
        Array.set(arr, 0, 3);
        System.out.println("修改后的第一个元素: " + Array.get(arr, 0));
    }
}

这里要注意一点,getComponentType( )返回的是数组元素的Class

暂时就写这么多,我看的书中还有反射在工厂模式中的应用

无非是用forName()方法替换一下,没什么可说的

我是个java初级黑,我恨java那种恶心的语法和设计

这都是为了Android,为了打基础,为了适应以后的工作

(0)

相关推荐

  • java反射机制示例详解

    1.什么是反射?一个类有多个组成部分,例如:成员变量,方法,构造方法等.反射就是加载类,并解剖出类的各个组成部分. 2.加载类java中有一个Class类用于代表某一个类的字节码.Class类既然代表某个类的字节码,那就要提供加载某个类字节码的方法:forName().   此方法用于加载某个类的字节码到内存中,并使用class对象进行封装.另外2种得到class对象的方式:类名.class对象.getClass() 先创建一个简单的Person类 复制代码 代码如下: public class

  • Java 反射获取类详细信息的常用方法总结

    类ReflectionDemo 复制代码 代码如下: package Reflection; @Deprecated public class ReflectionDemo {     private String pri_field;     public String pub_field;     public ReflectionDemo(){}     public ReflectionDemo(String name){}     private ReflectionDemo(Stri

  • Java 采用反射获取class属性值的实现代码

    原理:Java的反射能够获取属性的名称,然后通过invoke调用类的某个方法.比如有个属性叫userName,这个类写了个方法叫getUserName,通过invoke调用getUserName这个方法.代码如下 复制代码 代码如下: import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.HashMap;import java.util.Map;public class ParameterB

  • java根据方法名称取得反射方法的参数类型示例

    复制代码 代码如下: /** * 根据方法名称取得反射方法的参数类型(没有考虑同名重载方法使用时注意) * @param obj         类实例   * @param methodName  方法名 * @return * @throws ClassNotFoundException */public static Class[]  getMethodParamTypes(Object classInstance,  String methodName) throws ClassNotF

  • 基于Java回顾之反射的使用分析

    反射可以帮助我们查看指定类型中的信息.创建类型的实例,调用类型的方法.我们平时使用框架,例如Spring.EJB.Hibernate等都大量的使用了反射技术.反射简单示例 下面来演示反射相关的基本操作 首先是基础代码,我们定义一个接口及其实现,作为我们反射操作的目标: 复制代码 代码如下: interface HelloWorldService {     void sayHello(String name); } class MyHelloWorld implements HelloWorld

  • java反射android的r文件的示例

    动态取得R文件的int值,通过string-array name属性动态获取R.array.xxx的int值 复制代码 代码如下: //通过string-array name属性动态获取R.array.xxx的int值public CharSequence[] getListData(String name) {        try {            Class<?> arrayClass = getArrayResource().getClass();            Fie

  • java类加载器和类反射使用示例

    一.一个命令对应一个进程. 当我们启动一个Java程序,即启动一个main方法时,都将启动一个Java虚拟机进程,不管这个进程有多么复杂.而不同的JVM进程之间是不会相互影响的.这也就是为什么说,Java程序只有一个入口--main方法,让虚拟机调用.而两个mian方法,对应的是2个JVM进程,启动的是两个不同的类加载器,操作的实际上是不同的类.故而不会互相影响. 二.类加载. 当我们使用一个类,如果这个类还未加载到内存中,系统会通过加载.连接.初始化对类进行初始化. 1.类加载:指的是将类的c

  • java使用dom4j解析xml配置文件实现抽象工厂反射示例

    逻辑描述: 现在我们想在B层和D层加上接口层,并使用工厂.而我们可以将创建B和创建D看作是两个系列,然后就可以使用抽象工厂进行创建了. 配置文件:beans-config.xml.service-class与dao-class分别对应两个系列的产品.子菜单中id对应接口的命名空间,class对应实现类的命名空间. 复制代码 代码如下: [html] view plaincopyprint? <?xml version="1.0" encoding="UTF-8"

  • AJAX JavaScript反射机制的介绍

    什么是反射机制 反射机制指的是程序在运行时能够获取自身的信息.例如一个对象能够在运行时知道自己有哪些方法和属性. 在JavaScript中利用for(-in-)语句实现反射 在JavaScript中有一个很方便的语法来实现反射,即for(-in-)语句,其语法如下: for(var p in obj){ //语句 } 这里var p表示声明的一个变量,用以存储对象obj的属性(方法)名称,有了对象名和属性(方法)名,就可以使用方括号语法来调用一个对象的属性(方法): 复制代码 代码如下: for

  • Java反射机制的实现详解

    很多主流框架都使用了反射技术.像ssh框架都采用两种技术 xml做配置文件+反射技术. 与反射有关的类包. java.lang.reflect.*;和java.lang.Class; Java中所有类型(包括基本类型)都对应一个Class对象,这个Class就是java.lang.Class.即每一个类型,在Class中都有一个Class对象跟它对应.Class 没有公共构造方法.注意不是没有,是没有公共的. 如何获得Class对象 复制代码 代码如下: .针对每一个对象.getCalss(),

  • Java反射学习 getClass()函数应用

    Java反射学习 所谓反射,可以理解为在运行时期获取对象类型信息的操作.传统的编程方法要求程序员在编译阶段决定使用的类型,但是在反射的帮助下,编程人员可以动态获取这些信息,从而编写更加具有可移植性的代码.严格地说,反射并非编程语言的特性,因为在任何一种语言都可以实现反射机制,但是如果编程语言本身支持反射,那么反射的实现就会方便很多. 1,获得类型类 我们知道在Java中一切都是对象,我们一般所使用的对象都直接或间接继承自Object类.Object类中包含一个方法名叫getClass,利用这个方

  • java反射机制实战示例分享

    首先,我们来认识几个类. Class(java.lang.Class) Class对象是一个特殊对象,每一个类都有一个Class对象,用来创建该类的"常规"对象.可以通过对象的getClass()方法获取. 比如我们运行这一行代码: 复制代码 代码如下: System.out.println("测试".getClass().toString()); 得到的结果就是: 复制代码 代码如下: class java.lang.String Field(java.lang.

  • 传智播客学习之java 反射

    此外,毕老师为我们讲解了反射机制,虽然以后我们在开发过程中,不一定会涉及反射,但是反射确实java一种强大的工具,它使我们能够创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代表链接.例如在Tomcat类加载器这种机制被很多框架所使用. 一.什么是反射 反射的概念是由Smith在1982年首次提出,主要是指程序可以访问.检测和修改本身状态行为的一种能力.反射是java程序开发语言的特征之一,它也允许运行中的 Java 程序对自身进行检查,或者说"自审",并能直接操作程序的

  • java反射实现javabean转json实例代码

    ObjectToJson.java 复制代码 代码如下: package com.ObjectToJson; import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.Iterator; public class ObjectToJson {

  • java反射使用示例分享

    复制代码 代码如下: public class ReflexTest { public static void main(String[] args)      throws ClassNotFoundException, NoSuchMethodException, SecurityException,     IllegalAccessException, IllegalArgumentException, InvocationTargetException,      Instantiat

  • java反射应用详细介绍

    本篇文章依旧采用小例子来说明,因为我始终觉的,案例驱动是最好的,要不然只看理论的话,看了也不懂,不过建议大家在看完文章之后,在回过头去看看理论,会有更好的理解. 下面开始正文. [案例1]通过一个对象获得完整的包名和类名 复制代码 代码如下: package Reflect; /** * 通过一个对象获得完整的包名和类名 * */ class Demo{ //other codes... } class hello{ public static void main(String[] args)

  • Java反射机制的学习总结

    一.什么是反射机制 简单的来说,反射机制指的是程序在运行时能够获取自身的信息.在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息. 二.哪里用到反射机制 有些时候,我们用过一些知识,但是并不知道它的专业术语是什么,在刚刚学jdbc时用过一行代码, Class.forName("com.mysql.jdbc.Driver.class").newInstance();但是那时候只知道那行代码是生成驱动对象实例,并不知道它的具体含义.听了反射机制这节课后,才知道,原来这

  • Java 反射之私有字段和方法详细介绍

    尽管我们通常认为通过JAVA的反射机制来访问其它类的私有字段和私有方法是可行的,其实并没有那么困难. 注释:只有在单独的JAVA程序中运行该代码才有效,就像你做一些单元测试或者常规的程序.如果你尝试在JAVA APPLET内使用该方法,你需要稍稍修改SecurityManager.但是,因为你不是经常需要与它打交道,这里也就不再赘述了. 这里是本次内容的列表: 1.访问私有字段. 2.访问私有方法. 访问私有字段: 为了访问私有字段,你需要调用Class.getDeclaredField(Str

随机推荐