java厚积薄发之java反射机制

一.什么是java反射机制

了解什么是java反射机制,首选我们先了解一下动态语言这个概念,那么什么是动态语言呢?动态语言的定义“程序运行时,允许改变程序结构或者变量类型,这种语言称为动态语言”。
  从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。
  尽管在这样的定义与分类下Java不是动态语言,它却有着一个非常突出的动态相关机制:Reflection。这个字的意思是:反射、映像、倒影,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。
  换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。
  这种“看透”class的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。
       而JAVA反射机制就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

二.java反射机制的作用

      每个java类运行时都在JVM里表现为一个class对象,可通过类名.class,类型.getClass(),Class.forName("类名")等方法获取class对象,通过反编译,将.class->.java.,并且通过反射机制访问java对象的属性,方法,构造方法等。

      有时候换取一个类的属性,方法,构造方法不一定非要通过feflection,直接通过最原始的创建对象,获取属性,但是反射机制的存在大大增加了我们代码的灵活性。

三.反射机制的api

1.反射机制获取类有三种方法

    //第一种方式:  
    Classc1 = Class.forName("Employee");  
    //第二种方式:  
    //java中每个类型都有class 属性.  
    Classc2 = Employee.class;  
       
    //第三种方式:  
    //java语言中任何一个java对象都有getClass 方法  
    Employeee = new Employee();  
    Classc3 = e.getClass(); //c3是运行时类 (e的运行时类是Employee)  

2.获取类之后,创建对象

    Class c =Class.forName("Employee");  
      
    //创建此Class 对象所表示的类的一个新实例  
    Objecto = c.newInstance(); //调用了Employee的无参数构造方法.  

3.获取类中所有的构造方法,属性,方法

Class<?> classType = Class.forName("java.lang.String");
//返回class对象所对应的类或接口中,所声明的所有方法的数组(包括私有方法)
Method[] methods = classType.getDeclaredMethods();
//返回class对象所对应的类或接口中,所声明的所有属性(包括私有属性)
Field[] fields = classType.getDeclaredFields();
//返回class对象获得所有构造方法
 Constructor[] constructors=classType.getConstructors();

方法关键字

 

含义

getDeclaredMethods()

获取所有的方法

getReturnType()

获得方法的放回类型

getParameterTypes()

获得方法的传入参数类型

getDeclaredMethod("方法名",参数类型.class,……)

获得特定的方法

 

 

构造方法关键字

含义

getDeclaredConstructors()

获取所有的构造方法

getDeclaredConstructor(参数类型.class,……)

获取特定的构造方法

 

 

父类和父接口

含义

getSuperclass()

获取某类的父类

getInterfaces()

获取某类实现的接口


4.api测试

user类:

package com.tl.skyLine.model;

public class User{

    private String id;

    private String username;

    private String password;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}


测试类:

 @Test
    public void testReflecion() throws ClassNotFoundException {
//        Class c1 = Class.forName("com.tl.skyLine.model.User");
//        logger.info("-----c1-----" + c1);
        Class c2 = User.class;
        logger.info("-----c2-----" + c2);
//
//        User u=new User();
//        Class c3 = u.getClass();
//        logger.info("-----u-----"+u);
//        logger.info("-----c3-----"+c3);

        //建议使用第二种方法
        c2.getDeclaredMethods();
        Method[] methods = c2.getDeclaredMethods();
        Field[] fields = c2.getDeclaredFields();
        Constructor[] constructors = c2.getConstructors();

        for (Method m : methods) {
            logger.info("-----methods-----" + m);
        }

        for (Field f : fields) {
            logger.info("-----fields-----" + f);
        }

        for (Constructor c : constructors) {
            logger.info("-----constructors-----" + c);
        }
    }

打印结果:

[INFO][2016-02-27 14:48:53] -----c2-----class com.tl.skyLine.model.User 
[INFO][2016-02-27 14:48:53] -----methods-----public java.lang.String com.tl.skyLine.model.User.getId() 
[INFO][2016-02-27 14:48:53] -----methods-----public void com.tl.skyLine.model.User.setUsername(java.lang.String) 
[INFO][2016-02-27 14:48:53] -----methods-----public void com.tl.skyLine.model.User.setPassword(java.lang.String) 
[INFO][2016-02-27 14:48:53] -----methods-----public java.lang.String com.tl.skyLine.model.User.getUsername() 
[INFO][2016-02-27 14:48:53] -----methods-----public void com.tl.skyLine.model.User.setId(java.lang.String) 
[INFO][2016-02-27 14:48:53] -----methods-----public java.lang.String com.tl.skyLine.model.User.getPassword() 
[INFO][2016-02-27 14:48:53] -----fields-----private static final long com.tl.skyLine.model.User.serialVersionUID 
[INFO][2016-02-27 14:48:53] -----fields-----private java.lang.String com.tl.skyLine.model.User.id 
[INFO][2016-02-27 14:48:53] -----fields-----private java.lang.String com.tl.skyLine.model.User.username 
[INFO][2016-02-27 14:48:53] -----fields-----private java.lang.String com.tl.skyLine.model.User.password 
[INFO][2016-02-27 14:48:53] -----constructors-----public com.tl.skyLine.model.User() 

Process finished with exit code 0

四.具体代码实例

package com.tl.skyLine.aspect;

import java.lang.reflect.Method;

/**
 * Created by tl on 16/2/27.
 */

public class Temp {
    public int add(int param1, int param2) {
        return param1 + param2;

    }

    public String echo(String message) {
        return "Hello: " + message;
    }

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

        // 以前的常规执行手段
        Temp temp = new Temp();
        System.out.println("执行temp的add方法:" + temp.add(1, 2));
        System.out.println("执行temp的echo方法:" + temp.echo("Tom"));
        System.out.println("---------------------------");

        // 通过反射的方式

        // 第一步,获取Class对象
        // 前面用的方法是:Class.forName()方法获取
        // 这里用第二种方法,类名.class
        Class<?> classType = Temp.class;

        // 生成新的对象:用newInstance()方法
        Object tobject = classType.newInstance();
        System.out.println("tobject是Temp对象的实例吗:" + (tobject instanceof Temp)); // 输出true

        // 通过反射调用方法
        // 首先需要获得与该方法对应的Method对象
        // 第一个参数是方法名,第二个参数是这个方法所需要的参数的Class对象的数组(也就是方法参数)
        Method addMethod = classType.getMethod("add", new Class[]{int.class, int.class});
        // 等同于:
//        Method addMethod = classType.getMethod("add", int.class, int.class);
        // 调用目标方法
        Object result = addMethod.invoke(tobject, new Object[]{1, 2});
        System.out.println("反射调用temp的add方法:" + result); // 此时result是Integer类型

        //调用第二个方法
        Method echoMethod = classType.getDeclaredMethod("echo", new Class[]{String.class});
        Object result2 = echoMethod.invoke(tobject, new Object[]{"Tom"});
        System.out.println("反射调用temp的echo方法:" + result2);

    }
}

打印结果:

Connected to the target VM, address: '127.0.0.1:63034', transport: 'socket'
执行temp的add方法:3
执行temp的echo方法:Hello: Tom
---------------------------
tobject是Temp对象的实例吗:true
Disconnected from the target VM, address: '127.0.0.1:63034', transport: 'socket'
反射调用temp的add方法:3
反射调用temp的echo方法:Hello: Tom

Process finished with exit code 0




Java类加载器是负责加载Java类文件到JVM中的重要组件,它的主要作用是从磁盘或网络中加载类文件,并将其转化为JVM中的Class对象。Java类加载器按照加载类的范围可以分为以下三种: 1. 启动类加载器(Bootstrap ClassLoader):这是JVM内置的类加载器,它负责加载JVM运行时需要的核心类库,如java.lang包中的类等。这个类加载器是由C++编写的,所以在Java中看不到它的源代码。 2. 扩展类加载器(Extension ClassLoader):它负责加载Java的扩展类库,一般位于JRE的lib/ext目录下。这个类加载器是纯Java代码实现的,可以通过ClassLoader.getSystemClassLoader().getParent()方法获得它的父类加载器。 3. 应用程序类加载器(Application ClassLoader):也称为系统类加载器,它负责加载应用程序的类,一般是从CLASSPATH环境变量或者-D java.class.path选项所指定的目录或JAR文件中加载类。这个类加载器也是纯Java代码实现的,可以通过ClassLoader.getSystemClassLoader()方法获得它的实例。 总之,Java类加载器按照加载类的范围可以分为三种,分别是启动类加载器、扩展类加载器和应用程序类加载器。这三种类加载器按照加载的顺序依次向下委托加载类,如果当前类加载器无法加载某个类,则会将这个任务委托给它的父类加载器,直到系统的最顶层类加载器(启动类加载器)为止。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值