疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

Java反射探讨


 

       与反射有关的类包.

  java.lang.reflect.*;和java.lang.Class;

  Java中,反射式一种强大的工具。它让您能够创建灵活的代码,这些代码可以在运行时装配,无需在组件质检尽兴源代表链接。反射允许我们在编写与执行时,使我们的程序代码能够介入装载到JVM中的类的内部信息,而不是源代码中选定的类协作的代码。这种反射成为构建灵活的应用的主要工具。但需注意的是:如果使用不当,反射的成本很高。

  反射的一句总结:“反射就是把Java类中的各种成分映射成相应的java类--->Class”。

  什么时候使用反射呢?

  编译时根本无法预知该对象属于什么类,程序只能依靠运行时信息来发现对象的真实信息,这时就必须使用反射了。

  要是想得到对象真正的类型,就得使用反射。

  Class类和Class类实例

  Java程序中的各个Java类属于同一类事物,描述这类事物的Java类就是Class类。

  对比提问:众多的人用一个什么类表示?众多的Java类用一个什么类表示?

  人 à Person

  Java类 à Class

  对比提问: Person类代表人,它的实例对象就是张三,李四这样一个个具体的人,Class类代表Java类,它的各个实例对象又分别对应什么呢?

  对应各个类在内存中的字节码,例如,Person类的字节码,ArrayList类的字节码,等等;

  一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以它们在内存中的内容是不同的;

  一个类在虚拟机中只有一份字节码;

  获得Class对象

  如何得到各个字节码对应的实例对象?

  每个类被加载后,系统会为该类生成对应的Class对象,通过Class对象可以访问到JVM中的这个类,3种方式:

  使用Class类的forName(String className)静态方法,className表示全限定名;如String的全限定名:java.lang.String;

  调用某个类的class属性获取Class对象,如Date.class会返回Date类对应的Class对象(其实就是得到一个类的一份字节码文件);

  调用某个对象的getClass()方法。该方法属于Object类;

  1   /**

  2 * 第一种: 通过对象.class属性获得Class对象

  3 */

  4 Class clz1 = Person.class;

  5 Class clz2= Person.class;

  6 System.out.println(clz1==clz2);

  7 //上面结果是相等的,因为一个类在虚拟机中只有一份字节码;

  8 /**

  9 * 第二种:同过Class.forName(String className);得到Class对象

  10 * className表示全限定名;如String的全限定名:java.lang.String;

  11 */

  12 Class clz3=Class.forName("java.lang.String");

  13 /**

  14 * 第三种:通过对象getClass()方法得到Class对象。

  15 */

  16 String str = new String();

  17 Class strClass = str.getClass();

  1 /**

  2

  3 * 基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)

  4

  5 * 和关键字 void通过class属性也表示为 Class 对象;

  6

  7 * @author Leo

  8

  9 */

  10

  11 public class ClassDemo2

  12

  13 {

  14

  15 public static void main(String[] args) {

  16

  17 Class clz = int.class;

  18

  19 Class clz1 = Integer.class;

  20

  21 Class clz2=Integer.TYPE;

  22

  23 System.out.println(clz1==clz);//false

  24

  25 System.out.println(clz==clz2);//true

  26

  27 System.out.println(clz1==clz2);//false

  28

  29     }

  30

  31 }

  Class中-得到构造方法Constructor

  Constructor类用于描述类中的构造方法

  1 import java.lang.reflect.Constructor;

  2

  3 /**

  4

  5 Constructor getConstructor(Class... parameterTypes)

  6

  7 返回该Class对象表示类的指定的public构造方法;

  8

  9 Constructor[] getConstructors()

  10

  11 返回该Class对象表示类的所有public构造方法;

  12

  13 Constructor getDeclaredConstructor(Class... parameterTypes)

  14

  15 返回该Class对象表示类的指定的构造方法,和访问权限无关;

  16

  17 Constructor[] getDeclaredConstructors()

  18

  19 返回该Class对象表示类的所有构造方法,和访问权限无关;

  20

  21 */

  22

  23 public class ClassDemo3 {

  24

  25 public static void main(String[] args) throws Exception {

  26

  27 //获得class对象

  28

  29 Class clz = User.class;

  30

  31

  32

  33 //返回该Class对象表示类的所有public构造方法;

  34

  35 Constructor[] cs = clz.getConstructors();

  36

  37 for (Constructor constructor : cs) {

  38

  39 System.out.println("所有public修饰的构造方法---->"+constructor);

  40

  41 }

  42

  43

  44

  45 //返回该Class对象表示类的指定的public构造方法;

  46

  47 Constructor cs2 =clz.getConstructor(String.class);

  48

  49 System.out.println("指定的public修饰的构造方法---->"+cs2);

  50

  51

  52

  53 //返回该Class对象表示类的所有构造方法,和访问权限无关;

  54

  55 Constructor[] cs3=clz.getDeclaredConstructors();

  56

  57 for (Constructor constructor : cs3) {

  58

  59 System.out.println("所有构造方法---->"+constructor);

  60

  61 }

  62

  63

  64

  65 //返回该Class对象表示类的指定的构造方法,和访问权限无关;

  66

  67 Constructor cs4=clz.getDeclaredConstructor(Integer.class);

  68

  69 System.out.println("指定的构造方法--->"+cs4);

  70

  71 }

  72

  73 }

  74

  75 class User

  76

  77 {

  78

  79 //私有构造方法

  80

  81 private User(){}

  82

  83 private User(Integer age){}

  84

  85 //共有构造方法

  86

  87 public User(String name){}

  88

  89 public User(String name,Integer age){}

  90

  91 }

  Class中-得到方法Method

  Method类用于描述类中的方法

  1 import java.lang.reflect.Method;

  2

  3

  4

  5 /**

  6

  7 Method类用于描述类中的方法

  8

  9 Method getMethod(String name, Class ... parameterTypes)

  10

  11 返回该Class对象表示类和其父类的指定的public方法;

  12

  13 Method[] getMethods():

  14

  15 返回该Class对象表示类和其父类的所有public方法;

  16

  17 Method getDeclaredMethod(String name, Class... parameterTypes)

  18

  19 返回该Class对象表示类的指定的方法。和访问权限无关,但不包括继承的方法;

  20

  21 Method[] getDeclaredMethods():

  22

  23 获得类所有的方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法;

  24

  25 */

  26

  27 public class ClassDemo4

  28

  29 {

  30

  31 public static void main(String[] args) throws Exception {

  32

  33 Class clz = Student.class;

  34

  35 /**

  36

  37 * String name 代表方法名;

  38

  39 * Class ... parameterTypes 代表参数的 类型.class

  40

  41 */

  42

  43 //返回该Class对象表示类和其父类的指定的public方法;

  44

  45 Method md = clz.getMethod("reding",String.class);

  46

  47 System.out.println(md);

  48

  49 //返回该Class对象表示类的指定的方法。和访问权限无关,但不包括继承的方法;

  50

  51 Method md2 = clz.getDeclaredMethod("paoNiu");

  52

  53 System.out.println(md2);

  54

  55 //返回该Class对象表示类和其父类的所有public方法;

  56

  57 Method[] md3=clz.getMethods();

  58

  59 for (Method method : md3) {

  60

  61 System.out.println(method);

  62

  63 }

  64

  65 //获得类所有的方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法;

  66

  67 Method[] md4=clz.getDeclaredMethods();

  68

  69 for (Method method : md4) {

  70

  71 System.out.println(method);

  72

  73 }

  74

  75 }

  76

  77 }

  78

  79 class Student

  80

  81 {

  82

  83 public void reding(){}

  84

  85 public void reding(String name){}

  86

  87 private void paoNiu(){}

  88

  89 protected void sleep(){}

  90

  91 }

  92

  93

  Class中-得到字段Field

  Field类用于描述类中的字段

  1 import java.lang.reflect.Field;

  2

  3

  4

  5 /**

  6

  7 Field getField(String name)

  8

  9 返回该Class对象表示类和其父类的指定的public字段;

  10

  11 Field[] getFields()

  12

  13 返回该Class对象表示类和其父类的所有public字段;

  14

  15 Field getDeclaredField(String name)

  16

  17 返回该Class对象表示类的指定的字段和访问权限无关,但不包括继承的字段;

  18

  19 Field[] getDeclaredFields()

  20

  21 返回当前Class对象中公共、保护、默认(包)访问和私有字段,但不包括继承的字段;

  22

  23 */

  24

  25 public class ClassDemo5

  26

  27 {

  28

  29 public String gender;

  30

  31 public static void main(String[] args) throws Exception {

  32

  33 Class clz = Teacher.class;

  34

  35 /**

  36

  37 * String name 代表字段名;

  38

  39 */

  40

  41 //返回该Class对象表示类和其父类的指定的public字段;

  42

  43 Field fd = clz.getField("age");

  44

  45 System.out.println(fd);

  46

  47 // 返回该Class对象表示类的指定的字段和访问权限无关,但不包括继承的字段;

  48

  49 Field fd2 = clz.getDeclaredField("name");

  50

  51 System.out.println(fd2);

  52

  53 //返回该Class对象表示类和其父类的所有public字段;

  54

  55 Field[] fd3 = clz.getFields();

  56

  57 for (Field field : fd3) {

  58

  59 System.out.println(field);

  60

  61 }

  62

  63 //返回当前Class对象中公共、保护、默认(包)访问和私有字段,但不包括继承的字段;

  64

  65 Field[] fd4 = clz.getDeclaredFields();

  66

  67 for (Field field : fd4) {

  68

  69 System.out.println(field);

  70

  71 }

  72

  73 }

  74

  75 }

  76

  77 class Teacher extends ClassDemo5

  78

  79 {

  80

  81 private String name;

  82

  83 public Integer age;

  84

  85 protected String sex;

  86

  87 }

  使用反射创建对象:

  1 package 反射;

  2

  3 import java.lang.reflect.Constructor;

  4

  5 /**

  6 * 使用反射创建对象

  7 */

  8 public class ClassDemo6

  9 {

  10 public static void main(String[] args) throws Exception {

  11 /**

  12 * 第一种:

  13 * Class.newInstance():只能创建非private和无参的构造方法的对象

  14 * Computer c = clz.newInstance(); 等同于 Computer c = new Computer();

  15 */

  16 Class clz = Computer.class;

  17 Computer c = clz.newInstance();

  18 /**

  19 * 第二种:

  20 * 1.先得到一个指定的构造方法。

  21 * 2.调用构造器的一个方法:

  22 * newInstance(initargs)

  23 * initargs表示构造方法需要的实参

  24 * 3.调用Constructor父类的setAccessible(flag)方法设置私有构造方法是否可访问

  25 */

  26 Constructor con = clz.getDeclaredConstructor(String.class);

  27 con.setAccessible(true);

  28 c= con.newInstance("leo");

  29 System.out.println(c);

  30 }

  31 }

  32 class Computer

  33 {

  34 private Computer(String name){}

  35 public Computer()

  36 {

  37 System.out.println("public,无参!");

  38 }

  39 public String toString()

  40 {

  41 return "我已经创建!";

  42 }

  43 }

  使用反射调用对象里的方法

  1 package 反射;

  2

  3 import java.lang.reflect.Method;

  4 import java.util.ArrayList;

  5 import java.util.Arrays;

  6

  7 /**

  8 * 使用反射调用对象里面的方法

  9 */

  10 public class ClassDemo7

  11 {

  12 public static void main(String[] args) throws Exception {

  13 /**

  14 * 1、得到方法所在类的字节码。Class 对象

  15 * 2、获取方法。Method对象

  16 * 3、执行Method所表示的方法

  17 */

  18 //1、得到方法所在类的字节码。Class 对象

  19 Class clz = Car.class;

  20 // 2、获取方法。Method对象

  21 Method method1 = clz.getMethod("show1");

  22 Method method2 = clz.getDeclaredMethod("show2");

  23 Method method3 = clz.getMethod("show3",String.class);

  24 Method arry = clz.getMethod("arry");

  25 Method arry1 = clz.getMethod("arry1",String[].class);

  26 //3、执行Method所表示的方法

  27 /**

  28 * 调用父类的invoke(obj, args)方法;

  29 * obj:代表该方法所在的对象! 如果执行的方法是静态的,那么这个参数的实参可以直接是null

  30 * args:方法需要的实参

  31 * 返回的是Object对象

  32 */

  33 method2.setAccessible(true);

  34 method2.invoke(clz.newInstance());

  35 method1.invoke(clz.newInstance());

  36 method3.invoke(clz.newInstance(), "Leo");

  37 String[] str=(String[]) arry.invoke(clz.newInstance());

  38 for (String string : str) {

  39 System.out.println(string);

  40 }

  41 // arry1.invoke(clz.newInstance(), new String[]{"1","2"});//错误

  42 arry1.invoke(clz.newInstance(), (Object)new String[]{"1","2"});//正确

  43 }

  44 }

  45 class Car

  46 {

  47 public void show1()

  48 {

  49 System.out.println("我是公共的方法!");

  50 }

  51 private void show2()

  52 {

  53 System.out.println("我是私有的方法!");

  54 }

  55 public void show3(String name)

  56 {

  57 System.out.println("hello "+name+" 我是公共带参的方法!");

  58 }

  59 public String[] arry()

  60 {

  61 String[] str = new String[]{"1","2"};

  62 return str;

  63 }

  64 public void arry1(String[] str)

  65 {

  66 System.out.println(Arrays.toString(str));

  67 }

  68 }

  使用反射操作字段

  1 package 反射;

  2

  3 import java.lang.reflect.Field;

  4

  5 /**

  6 * 使用反射操作类的字段

  7 */

  8 public class ClassDemo8 {

  9 public static void main(String[] args) throws Exception

  10 {

  11 Class clz = CellPhone.class;

  12 Field f = clz.getDeclaredField("number");

  13 Field f2 = clz.getDeclaredField("brand");

  14 f.setAccessible(true);

  15 CellPhone cp = clz.newInstance();

  16 /**

  17 * 给字段赋值使用如下方法:

  18 * Object set(obj,value);

  19 * obj:字段所属的对象!

  20 * value:赋给字段的值。

  21 */

  22 f.setInt(cp, 123);

  23 f2.set(cp, "苹果");

  24 System.out.println(cp);

  25 /**

  26 * 取字段的值:

  27 * Object get(obj);

  28 * obj:字段所属的对象!

  29 */

  30 int number = f.getInt(cp);

  31 Object brand = f2.get(cp);

  32 System.out.println(number+""+brand);

  33 }

  34 }

  35 class CellPhone

  36 {

  37 private int number;

  38 public String brand;

  39 protected String color;

  40 public String toString() {

  41 return "CellPhone [number=" + number + ", brand=" + brand + ", color="

  42 + color + "]";

  43 }

  44 }

  使用反射操作范型创建对象.............

  1 package 反射;

  2

  3 /**

  4 * 使用反射操作范型

  5 */

  6 public class ClassDemo9 {

  7 /*

  8 * 需要强制转换类型

  9 */

  10 public static Object getBean(String className) throws Exception

  11 {

  12 return Class.forName(className).newInstance();

  13 }

  14 /*

  15 * 不需要强制转换类型

  16 */

  17 public static T getBean(String className,Class clz) throws Exception

  18 {

  19 Class ct = (Class) clz.forName(className);

  20 return ct.newInstance();

  21 }

  22 /*

  23 * 不需要强制转换类型

  24 */

  25 public static T getBean(Class clz) throws Exception

  26 {

  27 return clz.newInstance();

  28 }

  29 public static void main(String[] args) throws Exception {

  30 String str = (String)getBean("java.lang.String");

  31 String str2=getBean("java.lang.String",String.class);

  32 Integer number = getBean(Integer.class);

  33 }

  34 }