java学习笔记09--反射机制

什么是反射:

反射是java语言的一个特性,它允许程序在运行时来进行自我检查并且对内部的成员进行操作。例如它允许一个java的类获取他所有的成员变量和方法并且显示出来。
java的反射机制的实现要借助4个类:Class,Constructor,Field,Method 其中Class代表的是类对象,Constructor  类的构造器对象,Field  类的属性对象,Method

类的方法对象。通过这四个对象我们可以粗略的看到一个类的各个组成部分。

在正常情况下,必须知道一个类的完整路径之后才可以实例化对象,但是在java中也允许通过一个对象来找到其所在的类的信息,那么这实际上就是Class类的功能。

  1. package com.itmyhome;
  2. class A{
  3. }
  4. public class T {
  5. public static void main(String[] args) {
  6. // TODO Auto-generated method stub
  7. A a = new A();
  8. System.out.println(a.getClass().getName());  //com.itmyhome.A
  9. }
  10. }

Object类的支持

在Object类中定义了以下的方法,此方法将被所有子类继承:

public  final  Class getClass()

以上的方法返回值的类型是一个"Class"类,实际上此类是java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称。

Class类

Class本身表示一个类的本身,通过Class可以完整的得到一个类中的完整结构,包括此类中的方法定义,属性定义等。

实例化Class类对象

有三种方法实例化Class对象:

第一种:通过forName()方法

第二种:类.class

第三种:对象.getClass()

  1. package com.itmyhome;
  2. class A{
  3. }
  4. public class T {
  5. public static void main(String[] args) throws ClassNotFoundException {
  6. // TODO Auto-generated method stub
  7. Class<?> c1 = Class.forName("com.itmyhome.A");
  8. Class<?> c2 = A.class;
  9. Class<?> c3 = new A().getClass();
  10. System.out.println(c1.getName());
  11. System.out.println(c2.getName());
  12. System.out.println(c3.getName());
  13. }
  14. }

Class主要是反射的源头,不光可以取得对象所在类的信息,也可以直接通过Class类的方法进行对象的实例化操作正常情况下,使用关键字new为对象实例化,如果现在已经实例化好了Class对象,则就可以通过Class类中提供的

实例化对象

  1. package com.itmyhome;
  2. class Person {
  3. private String name;
  4. private int age;
  5. public String getName() {
  6. return name;
  7. }
  8. public void setName(String name) {
  9. this.name = name;
  10. }
  11. public int getAge() {
  12. return age;
  13. }
  14. public void setAge(int age) {
  15. this.age = age;
  16. }
  17. public String toString() {
  18. // TODO Auto-generated method stub
  19. return "name: " + name + ",age: " + age;
  20. }
  21. }
  22. public class T {
  23. public static void main(String[] args) throws ClassNotFoundException {
  24. Class<?> c = Class.forName("com.itmyhome.Person");
  25. Person person = null;
  26. try {
  27. person = (Person) c.newInstance();  //实例化对象
  28. } catch (InstantiationException e) {
  29. e.printStackTrace();
  30. } catch (IllegalAccessException e) {
  31. e.printStackTrace();
  32. }
  33. person.setName("itmyhome");
  34. person.setAge(23);
  35. System.out.println(person);
  36. }
  37. }

通过以上的代码,可以发现,即使不使用关键字new对象也可以进行实例化操作,反射的作用。

但是,在使用以上操作的时候有一点必须注意,在操作中类中必须存在无参构造方法,否则无法实例化

报以下异常

  1. java.lang.InstantiationException: com.itmyhome.Person
  2. at java.lang.Class.newInstance0(Class.java:340)
  3. at java.lang.Class.newInstance(Class.java:308)
  4. at com.itmyhome.T.main(T.java:35)
  5. Exception in thread "main" java.lang.NullPointerException
  6. at com.itmyhome.T.main(T.java:41)

对于以上的程序也并非没有解决的方法,也是可以通过其他的方式进行实例化操作的,只是在操作的时候需要明确的调用类中的构造方法,并将参数传递进去之后才可以进行实例化操作,操作步骤如下:

1、通过Class类中的getConstructors()取得本类中的全部构造方法。

2、向构造方法中传递一个对象数组进去,里面包含了构造方法中所需的各个参数。

3、之后通过Constructor实例化对象。

  1. package com.itmyhome;
  2. import java.lang.reflect.Constructor;
  3. class Person {
  4. private String name;
  5. private int age;
  6. public Person(String name,int age){
  7. this.name = name;
  8. this.age = age;
  9. }
  10. public String getName() {
  11. return name;
  12. }
  13. public void setName(String name) {
  14. this.name = name;
  15. }
  16. public int getAge() {
  17. return age;
  18. }
  19. public void setAge(int age) {
  20. this.age = age;
  21. }
  22. public String toString() {
  23. // TODO Auto-generated method stub
  24. return "name: " + name + ",age: " + age;
  25. }
  26. }
  27. public class T {
  28. public static void main(String[] args) throws ClassNotFoundException{
  29. Class<?> c = Class.forName("com.itmyhome.Person");
  30. Constructor<?> cons[] = c.getConstructors();
  31. Person person = null;
  32. try {
  33. person = (Person) cons[0].newInstance("itmyhome",23);  //实例化对象
  34. } catch (Exception e) {
  35. e.printStackTrace();
  36. }
  37. person.setName("itmyhome");
  38. person.setAge(23);
  39. System.out.println(person);
  40. }
  41. }

反射机制的深入----取得类的结构

在实际开发中,以上的程序就是反射应用最多的地方,当然,反射机制所提供的功能远不止如此,还可以通过反射得到一个类的完整结构,那么这就要使用到java.lang.reflect包中的以下几个类:

Constructor:表示类中的构造方法

Field:表示类中的属性

Method:表示类中的方法

这三个类都是AccessibleObject类中的子类

  1. package com.itmyhome;
  2. interface IPerson{
  3. public static final String NAME = "itmyhome";
  4. public String toSay();
  5. public String toEat(String name,int age);
  6. }
  7. class Person implements IPerson{
  8. private String name;
  9. private int age;
  10. public Person(){    //无参构造
  11. }
  12. public Person(String name,int age){
  13. this.name = name;
  14. this.age = age;
  15. }
  16. @Override
  17. public String toSay() {
  18. return "hello!";
  19. }
  20. @Override
  21. public String toEat(String name, int age) {
  22. return "name: "+name+",age: "+age;
  23. }
  24. public String getName() {
  25. return name;
  26. }
  27. public void setName(String name) {
  28. this.name = name;
  29. }
  30. public int getAge() {
  31. return age;
  32. }
  33. public void setAge(int age) {
  34. this.age = age;
  35. }
  36. }

取得类所实现的全部接口

要想取得一个类所实现的全部接口,则必须使用Class类中的getInterfaces()方法,此方法定义如下:

  1. public Class[] getInterfaces()

此方法返回一个Class类的对象数组,之后就可以直接利用Class类中的getName()方法输出即可。

因为一个类可以同时实现多个接口,所以在此处就以一个数组的形式返回实现的全部接口。

  1. public class T {
  2. public static void main(String[] args) throws Exception{
  3. Class<?> cl = Class.forName("com.itmyhome.Person");  //实例化对象
  4. Class<?> c[] = cl.getInterfaces();   //以数组形式返回实现的全部接口
  5. for (int i = 0; i < c.length; i++) {
  6. System.out.println(c[i].getName());   //输出接口名称
  7. }
  8. }
  9. }

取得类所继承的父类

一个类可以实现多个接口,但是只能继承一个父类,所以如果要想取得一个类的父类,可以直接使用Class类中的getSuperClass()方法。此方法定义如下:

  1. public Class<? super T> getSuperClass()

此方法返回的是Class实例,和之前的得到接口一样,可以通过getName()方法取得名次。

一个类只继承一个父类,如果一个类中没有明确的指明继承哪个类,则肯定继承的是Object类。

  1. public class T {
  2. public static void main(String[] args) throws Exception{
  3. Class<?> cl = Class.forName("com.itmyhome.Person");  //实例化对象
  4. Class<?> c = cl.getSuperclass();   //取得继承父类
  5. System.out.println(c.getName());
  6. }
  7. }

取得类中的全部构造方法

  1. public class T {
  2. public static void main(String[] args) throws Exception{
  3. Class<?> cl = Class.forName("com.itmyhome.Person");  //实例化对象
  4. Constructor<?> c[] = cl.getConstructors();
  5. for (int i = 0; i < c.length; i++) {
  6. System.out.println(c[i]);
  7. }
  8. }
  9. }

取得类中的方法

要想取得一个类中的全部方法,可以使用Class类中的getDeclaredMethods()方法,此方法返回一个Method类的对象数组,而如果要想进一步取得方法的具体信息,例如:方法的参数,抛出的异常等等,则就必须依靠Method类

public  Method[]  getDeclaredMethods()      输出本类中的全部方法

public  Method[]  getMethods()  输出全部的方法

  1. public class T {
  2. public static void main(String[] args) throws Exception{
  3. Class<?> cl = Class.forName("com.itmyhome.Person");  //实例化对象
  4. Method m1[] = cl.getMethods();
  5. for (int i = 0; i < m1.length; i++) {
  6. System.out.println(m1[i]);
  7. }
  8. System.out.println("*************");
  9. Method m2[] = cl.getDeclaredMethods();
  10. for (int i = 0; i < m2.length; i++) {
  11. System.out.println(m2[i]);
  12. }
  13. }
  14. }

取得类中的属性

public  Field[]  getFields()    得到实现的接口和父类中的公共属性

public  Field[]  getDeclaredFields()  得到本类中的全部属性

以上方法返回的都是Field的数组,每一个Field对象就表示类中的一个属性

  1. public class T {
  2. public static void main(String[] args) throws Exception{
  3. Class<?> cl = Class.forName("com.itmyhome.Person");  //实例化对象
  4. Field f1[] = cl.getFields();
  5. for (int i = 0; i < f1.length; i++) {
  6. System.out.println(f1[i]);
  7. }
  8. System.out.println("*********");
  9. Field f2[] = cl.getDeclaredFields();   //本类中的属性
  10. for (int i = 0; i < f2.length; i++) {
  11. System.out.println(f2[i]);
  12. }
  13. }
  14. }

java学习笔记09--反射机制的更多相关文章

  1. java学习笔记13--反射机制与动态代理

    本文地址:http://www.cnblogs.com/archimedes/p/java-study-note13.html,转载请注明源地址. Java的反射机制 在Java运行时环境中,对于任意 ...

  2. java学习笔记:反射

    1.什么是反射? Reflection(反射)是被视为动态语言的关键,反射机制允许程序做执行期间借助于ReflectionAPI取得任何类的内部信息,并能直接操作任意对象内部属性及方法 2.反射相关的 ...

  3. 8.2(java学习笔记)反射

    一.基础知识 对象是表示或封装一些数据,一个类被加载后JVM会创建一个对应该类的Class对象, 类的整个结构信息会被放在对应的对象中,通过这个对象我们可以获取改类的全部信息, 而这些操作称为反射. ...

  4. Java 学习笔记(15)——反射

    Java中的类文件最终会被编译为.class 文件,也就是Java字节码.这个字节码中会存储Java 类的相关信息.在JVM执行这些代码时首先根据 java 命令中指定的类名找到.class 文件然后 ...

  5. java学习笔记之反射—反射和工厂模式

    简单工厂模式又称为静态工厂方法模式,它是由工厂对象来决定要创建哪一种类的实例化对象. 静态工厂代码: class Factory{ private Factory() {} public static ...

  6. 【java学习笔记】反射基础

    一.反射 反射就是在剖析一个类,了解这个类的构造,创建这个类对应的对象. Class 代表字节码的类,代表类的类 Field 代表属性的类 Method 代表方法的类 Constructor 代表构造 ...

  7. java学习笔记之反射—Class类实例化和对象的反射实例化

    反射之中所有的核心操作都是通过Class类对象展开的,可以说Class类是反射操作的根源所在,但是这个类的实例化对象,可以采用三种方式完成. java.lang.Class类的定义: public f ...

  8. Java学习笔记__异常机制_try_catch_finally_return执行顺序

    package cn.xiaocangtian.Exception; import java.io.FileInputStream; import java.io.FileNotFoundExcept ...

  9. 1.13(java学习笔记)异常机制

    异常不同于错误,它是程序运行时产生的未知问题. 如果把程序比喻成一辆汽车,那么汽车开着开着突然前面出现了一个大石头挡住了路,这就叫异常. 那么出现了这个异常我们需要去处理,比如打电话给公路管理局,让它 ...

随机推荐

  1. mysql中IN和EXITS效率

    mysql中的in语句是把外表和内表作hash 连接.而exists语句是对外表作loop循环,每次loop循环再对内表进行查询.一直大家都觉得exists比in语句的效率要高.这样的说法事实上是不准 ...

  2. Java Socket实现HTTP客户端来理解Session和Cookie的区别和联系

    HTTP协议本身是无状态的,即使是同一台电脑同一个浏览器打开同一个页面两次,服务器不知道这两次请求是同一个客户端发送过来的,两次请求是完全独立的.例如,第一次请求时已经登录了,第二次再请求服务器会“忘 ...

  3. @Autowired 注释与@Qualifier 注释

    @Service("OrganDaoIbatis") public class OrganDaoIbatis extends BaseDao implements IOrganDa ...

  4. 1941. Scary Martian Word

    1941. Scary Martian Word 这道题 一个长度为3的字符串视为 一个 火星文 字母(ASCII 33-122) ,给出一个火星人认为恐怖的单词(由火星字母组成) 然后 给你一篇文章 ...

  5. 改变Emacs下的注释代码方式以支持当前行(未选中情况下)的注释/反注释

    Emacs下支持多行代码的注释/反注释,命令是comment-or-uncomment-region. 我喜欢把它绑定在快捷键C-c C-/上,如下: (global-set-key [?\C-c ? ...

  6. Linux编译多个不同目录下的文件以及静态库、动态库的使用

    先看两篇博文,作为基础知识.如果对C/C++编译链接过程都了解的话,可以跳过不看. http://www.firedragonpzy.com.cn/index.php/archives/2556 ht ...

  7. javascript面向对象基础讲解(工厂模式、构造函数模式、原型模式、混合模式、动态原型模式)

    面向对象可以把程序中的关键模块都视为对象,而模块拥有属性及方法.这样我们如果把一些属性及方法封装起来,日后使用将非常方便,也可以避免繁琐重复的工作.接下来将为大家讲解在JS中面向对象的实现.   工厂 ...

  8. css3 animation 参数详解

    animation: name 2s ease 0s 1 both有人知道这后面的参数都代表什么意思吗 name 就是你创建动画的名称 2S表示的时长 ease表示运动效果 0S表示延迟时间 1表示的 ...

  9. html5的自定义data-*属性和jquery的data()方法的使用

    人们总喜欢往HTML标签上添加自定义属性来存储和操作数据.但这样做的问题是,你不知道将来会不会有其它脚本把你的自定义属性给重置掉,此外,你这样做也会导致html语法上不符合Html规范,以及一些其它副 ...

  10. leetcode先刷_Path Sum

    水的问题不解释,具有参数保持部和,当它到达一个叶子节点,推断是否与给予平等. 需要注意的是节点在树中的数目值它可以是正的或负.它不使用,修剪.有仅仅存在罐.因此,关于或代表最终结果的字. bool h ...