1反射机制是什么

反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

2反射机制能做什么

反射机制主要提供了以下功能:

  • 在运行时判断任意一个对象所属的类;

  • 在运行时构造任意一个类的对象;

  • 在运行时判断任意一个类所具有的成员变量和方法;

  • 在运行时调用任意一个对象的方法;

  • 生成动态代理。

3反射机制的相关API

通过一个对象获得完整的包名和类名

 package net.xsoftlab.baike;

 public class TestReflect {
     public static void main(String[] args) throws Exception {
         TestReflect testReflect = new TestReflect();
         System.out.println(testReflect.getClass().getName());
         // 结果 net.xsoftlab.baike.TestReflect
     }
 }

实例化Class类对象

 package net.xsoftlab.baike;

 public class TestReflect {
     public static void main(String[] args) throws Exception {
         Class<?> class1 = null;
         Class<?> class2 = null;
         Class<?> class3 = null;
         // 一般采用这种形式
         class1 = Class.forName("net.xsoftlab.baike.TestReflect");
         class2 = new TestReflect().getClass();
         class3 = TestReflect.class;
         System.out.println("类名称   " + class1.getName());
         System.out.println("类名称   " + class2.getName());
         System.out.println("类名称   " + class3.getName());
     }
 }

获取一个对象的父类与实现的接口

 package net.xsoftlab.baike;
 import java.io.Serializable;
 public class TestReflect implements Serializable {
     private static final long serialVersionUID = -2862585049955236662L;
     public static void main(String[] args) throws Exception {
         Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
         // 取得父类
         Class<?> parentClass = clazz.getSuperclass();
         System.out.println("clazz的父类为:" + parentClass.getName());
         // clazz的父类为: java.lang.Object
         // 获取所有的接口
         Class<?> intes[] = clazz.getInterfaces();
         System.out.println("clazz实现的接口有:");
         for (int i = 0; i < intes.length; i++) {
             System.out.println((i + 1) + ":" + intes[i].getName());
         }
         // clazz实现的接口有:
         // 1:java.io.Serializable
     }
 }

获取某个类中的全部构造函数 - 详见下例

通过反射机制实例化一个类的对象

 package net.xsoftlab.baike;
 import java.lang.reflect.Constructor;
 public class TestReflect {
     public static void main(String[] args) throws Exception {
         Class<?> class1 = null;
         class1 = Class.forName("net.xsoftlab.baike.User");
         // 第一种方法,实例化默认构造方法,调用set赋值
         User user = (User) class1.newInstance();
         user.setAge(20);
         user.setName("Rollen");
         System.out.println(user);
         // 结果 User [age=20, name=Rollen]
         // 第二种方法 取得全部的构造函数 使用构造函数赋值
         Constructor<?> cons[] = class1.getConstructors();
         // 查看每个构造方法需要的参数
         for (int i = 0; i < cons.length; i++) {
             Class<?> clazzs[] = cons[i].getParameterTypes();
             System.out.print("cons[" + i + "] (");
             for (int j = 0; j < clazzs.length; j++) {
                 if (j == clazzs.length - 1)
                     System.out.print(clazzs[j].getName());
                 else
                     System.out.print(clazzs[j].getName() + ",");
             }
             System.out.println(")");
         }
         // 结果
         // cons[0] (java.lang.String)
         // cons[1] (int,java.lang.String)
         // cons[2] ()
         user = (User) cons[0].newInstance("Rollen");
         System.out.println(user);
         // 结果 User [age=0, name=Rollen]
         user = (User) cons[1].newInstance(20, "Rollen");
         System.out.println(user);
         // 结果 User [age=20, name=Rollen]
     }
 }
 class User {
     private int age;
     private String name;
     public User() {
         super();
     }
     public User(String name) {
         super();
         this.name = name;
     }
     public User(int age, String name) {
         super();
         this.age = age;
         this.name = name;
     }
     public int getAge() {
         return age;
     }
     public void setAge(int age) {
         this.age = age;
     }
     public String getName() {
         return name;
     }
     public void setName(String name) {
         this.name = name;
     }
     @Override
     public String toString() {
         return "User [age=" + age + ", name=" + name + "]";
     }
 }

获取某个类的全部属性

 package net.xsoftlab.baike;
 import java.io.Serializable;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 public class TestReflect implements Serializable {
     private static final long serialVersionUID = -2862585049955236662L;
     public static void main(String[] args) throws Exception {
         Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
         System.out.println("===============本类属性===============");
         // 取得本类的全部属性
         Field[] field = clazz.getDeclaredFields();
         for (int i = 0; i < field.length; i++) {
             // 权限修饰符
             int mo = field[i].getModifiers();
             String priv = Modifier.toString(mo);
             // 属性类型
             Class<?> type = field[i].getType();
             System.out.println(priv + " " + type.getName() + " " + field[i].getName() + ";");
         }

         System.out.println("==========实现的接口或者父类的属性==========");
         // 取得实现的接口或者父类的属性
         Field[] filed1 = clazz.getFields();
         for (int j = 0; j < filed1.length; j++) {
             // 权限修饰符
             int mo = filed1[j].getModifiers();
             String priv = Modifier.toString(mo);
             // 属性类型
             Class<?> type = filed1[j].getType();
             System.out.println(priv + " " + type.getName() + " " + filed1[j].getName() + ";");
         }
     }
 }

获取某个类的全部方法

 package net.xsoftlab.baike;
 import java.io.Serializable;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 public class TestReflect implements Serializable {
     private static final long serialVersionUID = -2862585049955236662L;
     public static void main(String[] args) throws Exception {
         Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
         Method method[] = clazz.getMethods();
         for (int i = 0; i < method.length; ++i) {
             Class<?> returnType = method[i].getReturnType();
             Class<?> para[] = method[i].getParameterTypes();
             int temp = method[i].getModifiers();
             System.out.print(Modifier.toString(temp) + " ");
             System.out.print(returnType.getName() + "  ");
             System.out.print(method[i].getName() + " ");
             System.out.print("(");
             for (int j = 0; j < para.length; ++j) {
                 System.out.print(para[j].getName() + " " + "arg" + j);
                 if (j < para.length - 1) {
                     System.out.print(",");
                 }
             }
             Class<?> exce[] = method[i].getExceptionTypes();
             if (exce.length > 0) {
                 System.out.print(") throws ");
                 for (int k = 0; k < exce.length; ++k) {
                     System.out.print(exce[k].getName() + " ");
                     if (k < exce.length - 1) {
                         System.out.print(",");
                     }
                 }
             } else {
                 System.out.print(")");
             }
             System.out.println();
         }
     }
 }

通过反射机制调用某个类的方法

 package net.xsoftlab.baike;
 import java.lang.reflect.Method;
 public class TestReflect {
     public static void main(String[] args) throws Exception {
         Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
         // 调用TestReflect类中的reflect1方法
         Method method = clazz.getMethod("reflect1");
         method.invoke(clazz.newInstance());
         // Java 反射机制 - 调用某个类的方法1.
         // 调用TestReflect的reflect2方法
         method = clazz.getMethod("reflect2", int.class, String.class);
         method.invoke(clazz.newInstance(), 20, "张三");
         // Java 反射机制 - 调用某个类的方法2.
         // age -> 20. name -> 张三
     }
     public void reflect1() {
         System.out.println("Java 反射机制 - 调用某个类的方法1.");
     }
     public void reflect2(int age, String name) {
         System.out.println("Java 反射机制 - 调用某个类的方法2.");
         System.out.println("age -> " + age + ". name -> " + name);
     }
 }

通过反射机制操作某个类的属性

 package net.xsoftlab.baike;
 import java.lang.reflect.Field;
 public class TestReflect {
     private String proprety = null;
     public static void main(String[] args) throws Exception {
         Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
         Object obj = clazz.newInstance();
         // 可以直接对 private 的属性赋值
         Field field = clazz.getDeclaredField("proprety");
         field.setAccessible(true);
         field.set(obj, "Java反射机制");
         System.out.println(field.get(obj));
     }
 }

反射机制的动态代理

 // 获取类加载器的方法
 TestReflect testReflect = new TestReflect();
         System.out.println("类加载器  " + testReflect.getClass().getClassLoader().getClass().getName());
 package net.xsoftlab.baike;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 //定义项目接口
 interface Subject {
     public String say(String name, int age);
 }
 // 定义真实项目
 class RealSubject implements Subject {
     public String say(String name, int age) {
         return name + "  " + age;
     }
 }
 class MyInvocationHandler implements InvocationHandler {
     private Object obj = null;
     public Object bind(Object obj) {
         this.obj = obj;
         return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
     }
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
         Object temp = method.invoke(this.obj, args);
         return temp;
     }
 }
 /**
  * 在java中有三种类类加载器。
  *
  * 1)Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。
  *
  * 2)Extension ClassLoader 用来进行扩展类的加载,一般对应的是jrelibext目录中的类
  *
  * 3)AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。
  *
  * 如果想要完成动态代理,首先需要定义一个InvocationHandler接口的子类,已完成代理的具体操作。
  *
  * @author xsoftlab.net
  *
  */
 public class TestReflect {
     public static void main(String[] args) throws Exception {
         MyInvocationHandler demo = new MyInvocationHandler();
         Subject sub = (Subject) demo.bind(new RealSubject());
         String info = sub.say("Rollen", 20);
         System.out.println(info);
     }
 }

4反射机制的应用实例

在泛型为Integer的ArrayList中存放一个String类型的对象。

 package net.xsoftlab.baike;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 public class TestReflect {
     public static void main(String[] args) throws Exception {
         ArrayList<Integer> list = new ArrayList<Integer>();
         Method method = list.getClass().getMethod("add", Object.class);
         method.invoke(list, "Java反射机制实例。");
         System.out.println(list.get(0));
     }
 }

通过反射取得并修改数组的信息

 package net.xsoftlab.baike;
 import java.lang.reflect.Array;
 public class TestReflect {
     public static void main(String[] args) throws Exception {
         int[] temp = { 1, 2, 3, 4, 5 };
         Class<?> demo = temp.getClass().getComponentType();
         System.out.println("数组类型: " + demo.getName());
         System.out.println("数组长度  " + Array.getLength(temp));
         System.out.println("数组的第一个元素: " + Array.get(temp, 0));
         Array.set(temp, 0, 100);
         System.out.println("修改之后数组第一个元素为: " + Array.get(temp, 0));
     }
 }

通过反射机制修改数组的大小

 package net.xsoftlab.baike;
 import java.lang.reflect.Array;
 public class TestReflect {
     public static void main(String[] args) throws Exception {
         int[] temp = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
         int[] newTemp = (int[]) arrayInc(temp, 15);
         print(newTemp);
         String[] atr = { "a", "b", "c" };
         String[] str1 = (String[]) arrayInc(atr, 8);
         print(str1);
     }
     // 修改数组大小
     public static Object arrayInc(Object obj, int len) {
         Class<?> arr = obj.getClass().getComponentType();
         Object newArr = Array.newInstance(arr, len);
         int co = Array.getLength(obj);
         System.arraycopy(obj, 0, newArr, 0, co);
         return newArr;
     }
     // 打印
     public static void print(Object obj) {
         Class<?> c = obj.getClass();
         if (!c.isArray()) {
             return;
         }
         System.out.println("数组长度为: " + Array.getLength(obj));
         for (int i = 0; i < Array.getLength(obj); i++) {
             System.out.print(Array.get(obj, i) + " ");
         }
         System.out.println();
     }
 }

将反射机制应用于工厂模式

package net.xsoftlab.baike;
interface fruit {
    public abstract void eat();
}
class Apple implements fruit {
    public void eat() {
        System.out.println("Apple");
    }
}
class Orange implements fruit {
    public void eat() {
        System.out.println("Orange");
    }
}
class Factory {
    public static fruit getInstance(String ClassName) {
        fruit f = null;
        try {
            f = (fruit) Class.forName(ClassName).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return f;
    }
}

public class TestReflect {
    public static void main(String[] args) throws Exception {
        fruit f = Factory.getInstance("net.xsoftlab.baike.Apple");
        if (f != null) {
            f.eat();
        }
    }
}

反射是Java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接。但是反射使用不当会成本很高!

反射机制的作用:

1,反编译:.class-->.java

2,通过反射机制访问java对象的属性,方法,构造方法等

在这里先看一下sun为我们提供了那些反射机制中的类:

java.lang.Class;

java.lang.reflect.Constructor;

java.lang.reflect.Field;

java.lang.reflect.Method;

java.lang.reflect.Modifier;

具体功能实现:

1.反射机制获取类有三种方法,我们来获取Employee类型

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

2.创建对象:获取类以后我们来创建它的对象,利用newInstance:

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

3.获取属性:分为所有的属性和指定的属性:

a.先看获取所有的属性的写法:

               //获取整个类
             Class c = Class.forName("java.lang.Integer");
               //获取所有的属性?
             Field[] fs = c.getDeclaredFields();  

             //定义可变长的字符串,用来存储属性
             StringBuffer sb = new StringBuffer();
             //通过追加的方法,将每个属性拼接到此字符串中
             //最外边的public定义
             sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() +"{\n");
             //里边的每一个属性
             for(Field field:fs){
                 sb.append("\t");//空格
                 sb.append(Modifier.toString(field.getModifiers())+" ");//获得属性的修饰符,例如public,static等等
                 sb.append(field.getType().getSimpleName() + " ");//属性的类型的名字
                 sb.append(field.getName()+";\n");//属性的名字+回车
             }  

             sb.append("}");  

             System.out.println(sb);

b.获取特定的属性,对比着传统的方法来学习:

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

 <span style="white-space:pre">  </span>//以前的方式:
     /*
     User u = new User();
     u.age = 12; //set
     System.out.println(u.age); //get
     */  

     //获取类
     Class c = Class.forName("User");
     //获取id属性
     Field idF = c.getDeclaredField("id");
     //实例化这个类赋给o
     Object o = c.newInstance();
     //打破封装
     idF.setAccessible(true); //使用反射机制可以打破封装性,导致了java对象的属性不安全。
     //给o对象的id属性赋值"110"
     idF.set(o, "110"); //set
     //get
     System.out.println(idF.get(o));
 }  

4.获取方法,和构造方法,不再详细描述,只来看一下关键字:

方法关键字

含义

getDeclaredMethods()

获取所有的方法

getReturnType()

获得方法的放回类型

getParameterTypes()

获得方法的传入参数类型

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

获得特定的方法

构造方法关键字

含义

getDeclaredConstructors()

获取所有的构造方法

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

获取特定的构造方法

父类和父接口

含义

getSuperclass()

获取某类的父类

getInterfaces()

获取某类实现的接口

这样我们就可以获得类的各种内容,进行了反编译。对于JAVA这种先编译再运行的语言来说,反射机制可以使代码更加灵活,更加容易实现面向对象。

5.反射加配置文件,使我们的程序更加灵活:

在设计模式学习当中,学习抽象工厂的时候就用到了反射来更加方便的读取数据库链接字符串等,当时不是太理解,就照着抄了。看一下.NET中的反射+配置文件的使用:

当时用的配置文件是app.config文件,内容是XML格式的,里边填写链接数据库的内容:

  <configuration>
 lt;appSettings>
 <add     key=""  value=""/>
 lt;/appSettings>
 </configuration>  

反射的写法:  assembly.load("当前程序集的名称").CreateInstance("当前命名空间名称".要实例化的类名);

这样的好处是很容易的方便我们变换数据库,例如我们将系统的数据库从SQL Server升级到Oracle,那么我们写两份D层,在配置文件的内容改一下,或者加条件选择一下即可,带来了很大的方便。

当然了,JAVA中其实也是一样,只不过这里的配置文件为.properties,称作属性文件。通过反射读取里边的内容。这样代码是固定的,但是配置文件的内容我们可以改,这样使我们的代码灵活了很多!

综上为,JAVA反射的学习,灵活地运用它,能够使我们的代码更加灵活,但是它也有它的缺点,就是运用它会使我们的软件的性能降低,复杂度增加,所以还要我们慎重的使用它。

Class类与Java反射的更多相关文章

  1. 如何防止JAVA反射对单例类的攻击?

    在我的上篇随笔中,我们知道了创建单例类有以下几种方式: (1).饿汉式; (2).懒汉式(.加同步锁的懒汉式.加双重校验锁的懒汉式.防止指令重排优化的懒汉式); (3).登记式单例模式; (4).静态 ...

  2. 非常好的Java反射例子

    1.Java反射的概念 反射含义:可以获取正在运行的Java对象. 2.Java反射的功能 1)可以判断运行时对象所属的类 2)可以判断运行时对象所具有的成员变量和方法 3)通过反射甚至可以调用到pr ...

  3. java反射之Constructor简单应用

    Constructor类是java反射中重要的类,它是对类中构造器的描述的类.类似于Method(对类中方法的描述的类),Field(对类中属性的描述的类). 通过创建Constructor的对象实例 ...

  4. java反射 实例

    首先介绍几个概念: 1.Java反射的概念 反射含义:可以获取正在运行的Java对象. 2.Java反射的功能 1)可以判断运行时对象所属的类 2)可以判断运行时对象所具有的成员变量和方法 3)通过反 ...

  5. Java反射探索研究(转)

    林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankakay 摘要:本文详细深入讲解是Java中反射的机制,并介绍了如何通过反射来生成对象.调用函数.取得 ...

  6. java反射知识点总结

    一.java反射基础 1.1 什么叫java反射? 答:程序运行期间,动态的获取类的基本信息.比如:创建对象,调用类的方法,获得类的基本结构.这样给程序设计提供了很大的灵活性.个人总结就是:根据动态需 ...

  7. java反射机制与动态代理

    在学习HadoopRPC时.用到了函数调用.函数调用都是採用的java的反射机制和动态代理来实现的,所以如今回想下java的反射和动态代理的相关知识. 一.反射 JAVA反射机制定义: JAVA反射机 ...

  8. 【转】非常好的Java反射例子

    转自 http://www.douban.com/note/306848299/ 原文: 1.Java反射的概念 反射含义:可以获取正在运行的Java对象. 2.Java反射的功能 1)可以判断运行时 ...

  9. java反射机制梳理

    java反射机制梳理 Java反射简介 反射简介 编译和运行 编译时刻加载类是静态加载类.运行时刻加载类是动态加载类 要让Java程序能够运行,那么就得让Java类要被Java虚拟机加载.Java类如 ...

随机推荐

  1. Redis的部署及使用

    Redis Memcached与Redis的对比 Memcached: 优点: 1. 纯set get性能好 2. 开发都会用,易用简单 4. 可用于存放session 缺点: 1. 不支持持久化 2 ...

  2. 非极大值抑制(Non-Maximum Suppression,NMS)

    概述 非极大值抑制(Non-Maximum Suppression,NMS),顾名思义就是抑制不是极大值的元素,可以理解为局部最大搜索.这个局部代表的是一个邻域,邻域有两个参数可变,一是邻域的维数,二 ...

  3. 监听 window.open 打开的窗口关闭并回调

    第三方的登录的解决方案通常有两种方式,一是打开一个新的标签页,然后登录回调回来: 二是通过父窗口打开一个子窗体去第三方登录,登陆成功时关掉子窗体回到父窗口. 问题来了 我的父窗体怎么样才知道子窗体被关 ...

  4. Android笔记: 播放提示音 的简单方法

    public static void sendSound(Context mContext) { //上下文 Uri mUri= RingtoneManager.getDefaultUri(Ringt ...

  5. MSF初体验 - kali linux 入侵XP系统

    最近做某安全竞赛平台的比赛,真正开始接触Metasploit这一渗透神器,同时也是装逼神器(2333-.),下面记录一下初步使用Metasploit的过程.首先在百度百科摘录了一段关于Metasplo ...

  6. 关于tomcat的Unsupported major.minor version 51.0问题记录

    今天在构建一个应用时使用了注解的方式,可能是别的原因,正常访问一个servlet的时候报了一个从来没见过的错误. 2017-5-12 15:54:52 org.apache.catalina.core ...

  7. python3 安装及项目管理安装

    python3 一.下载安装 地址:https://www.python.org/downloads/ 安装:傻瓜式安装:我的目录如下 二.环境配置 [右键计算机]-->[属性]-->[高 ...

  8. selenium,html高宽设置成了0,会影响元素可见性,怎么手动修改某个元素的高宽?

     问题:要js的话,需要用webelment,此时元素已经是不可见了   ((JavascriptExecutor) this.driver).executeScript("argument ...

  9. mysql互换表中两列数据

    在开发过程中,有时由于业务等需要把一个表中的两列数据进行交换. 解决方案 使用update命令,这完全得益于MySQL SQL命令功能的强大支持. 表格中原来数据类似如下: select * from ...

  10. TC358775XBG:MIPI DSI转双路LVDS芯片简介

    TC358775XBG是一颗MIPI DSI转双路LVDS芯片,通信方式:IIC/MIPI command mode,分辨率1920*1200,封装形式:BGA64.