java通常是先有类再有对象,有对象我就可以调用方法或者属性。

反射其实是通过Class对象来调用类里面的方法。通过反射可以调用私有方法和私有属性。大部分框架都是运用反射原理。
 
如何获得Class对象:
1. 通过一个对象获得完整的包名和类名
  1. package Reflect;
    /**
    * 通过一个对象获得完整的包名和类名
    * */
    class Demo{
    //other codes...
    } class hello{
    public static void main(String[] args) {
    Demo demo=new Demo();
    System.out.println(demo.getClass().getName());
    }
    }
【运行结果】:Reflect.Demo
2. 通过类名实例化Class类对象(两种方式)
  1. package Reflect;
    class Demo{
    //other codes...
    }
    class hello{
    public static void main(String[] args) {
    Class<?> demo1=null;
    Class<?> demo2=null;
    Class<?> demo3=null;
    try{
    //一般尽量采用这种形式
    demo1=Class.forName("Reflect.Demo");
    }catch(Exception e){
    e.printStackTrace();
    }
    demo2=new Demo().getClass();
    demo3=Demo.class; System.out.println("类名称 "+demo1.getName());
    System.out.println("类名称 "+demo2.getName());
    System.out.println("类名称 "+demo3.getName()); }
    }
【运行结果】:
类名称   Reflect.Demo
类名称   Reflect.Demo
类名称   Reflect.Demo
 
Class与Object区分:
Class是类的类类型。类类型就是指类的Class类型。
在java中类,接口,数组 ,都可以抽象称为一个Class的对象。该Class对象代表运行时的组件。并且采用了泛型的技术来表述所代表的类型。
Object是所有类的父类。
 
Class获取类信息的常用方法
  1. package reflect;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    import org.omg.CORBA.PUBLIC_MEMBER;
    /**
    * 五个函数:(public static void)
    * ClassUtil.printClassMessage(Object obj);
    * ClassUtil.printFieldMessage(Object obj);
    * ClassUtil.printConstructorMessage(Object obj);
    * ClassUtil.printInterfacesMessage(Object obj);
    * ClassUtil.printSuperclassMessage(Object obj);
    *
    * @author sargeles
    */
    public class ClassUtil {
    /**
    * 打印类的信息,包括五个函数。
    *
    * @param obj
    *
    */
    public static void printClassMessage(Object obj) {
    // 要获取类的信息,首先要获取类的类类型
    Class c = obj.getClass();// 传递的是哪个子类的对象,c就是该子类的类类型
    // 获取类的名称
    System.out.println("类的名称是:" + c.getName());
    System.out.println("类的成员方法有:");
    /*
    * Method类,方法对象 一个成员方法就是一个Method对象
    * getMethods()方法获取的是所有的public的方法,包括从父类继承而来的
    * getDeclareMethods()获取的是所有该类自己声明的方法,不问访问权限
    */
    Method[] ms = c.getMethods();
    for (Method m : ms) {
    // public int getModifiers()方法是公有的,可以获取修饰符信息,将其包装成一个int。
    int mo = m.getModifiers();
    // Modifier封装了解读带有修饰符信息的int的方法。这些方法都是静态的。可以直接用。
    System.out.print(Modifier.toString(mo) + " ");
    // 得到方法返回值类型的类类型
    Class returnType = m.getReturnType();
    System.out.print(returnType.getName() + " ");
    // 得到方法的名称
    System.out.print(m.getName() + "(");
    // 获取参数类型--->得到的是参数列表的类型的类类型
    Class[] paramTypes = m.getParameterTypes();
    for (int i = 0; i < paramTypes.length; i++) {
    if (i > 0)
    System.out.print(",");
    System.out.print(paramTypes[i].getName());
    }
    System.out.println(")");
    }
    }
    /**
    * 获取成员变量的信息(自己声明的)
    *
    * @param obj
    */
    public static void printFieldMessage(Object obj) {
    // 要获取类的信息,首先要获取类的类类型
    Class c = obj.getClass();// 传递的是哪个子类的对象,c就是该子类的类类型
    System.out.println("类的名称是:" + c.getName());
    System.out.println("类的成员变量有:");
    /*
    * 成员变量也是对象 java.lang.reflect.Field Field类封装了关于成员变量的操作
    * getFields()方法获取的是所有public的成员变量的信息
    * getDeclaredFields()获取的是该类自己声明的成员变量的信息
    */
    Field[] fs = c.getDeclaredFields();
    for (Field field : fs) {
    // 获得成员变量的类型的类类型
    Class fieldType = field.getType();
    String typeName = fieldType.getName();
    // 得到成员变量的名字
    String fieldName = field.getName();
    System.out.println(typeName + " " + fieldName);
    }
    }
    /**
    * 获取类的构造函数信息
    *
    * @param obj
    */
    public static void printConstructorMessage(Object obj) {
    Class c = obj.getClass();
    System.out.println("类的名称是:" + c.getName());
    System.out.println("类的构造函数有:");
    /*
    * 构造函数也是对象 java.lang.Constructor中封装了构造函数的信息
    * getConstructors获取所有的public的构造函数 getDeclaredConstructors得到所有的构造函数
    */
    Constructor[] cs = c.getDeclaredConstructors();
    for (Constructor constructor : cs) {
    // java.lang.Class.getModifiers()方法是公有本地的,可以获取修饰符信息,将其包装成一个int。
    int mo = constructor.getModifiers();
    // Modifier封装了解读带有修饰符信息的int的方法。这些方法都是静态的。可以直接用。
    System.out.print(Modifier.toString(mo) + " ");
    System.out.print(constructor.getName() + "(");
    // 获取构造函数的参数列表--->得到的是参数列表的类类型
    Class[] paramTypes = constructor.getParameterTypes();
    for (int i = 0; i < paramTypes.length; i++) {
    if (i > 0)
    System.out.print(",");
    System.out.print(paramTypes[i].getName());
    }
    System.out.println(")");
    }
    }
    /**
    * 类的接口信息
    *
    * @param obj
    */
    public static void printInterfacesMessage(Object obj) {
    Class c = obj.getClass();
    System.out.println("类的名称是:" + c.getName());
    System.out.println("类实现的接口有:");
    /*
    * 接口类也是对象,因为接口也是类类型的一种,所以是Class的泛型。
    */
    Class[] intes = c.getInterfaces();
    for (Class classes : intes) {
    // 获取每个接口的名字,然后输出。
    System.out.println(classes.getName());
    }
    }
    /**
    * 类的父类信息
    *
    * @param obj
    */
    public static void printSuperclassMessage(Object obj) {
    Class c = obj.getClass();
    System.out.println("类的名称是:" + c.getName());
    System.out.print("类的父类是:");
    /*
    * 父类只可能有一个,所以不用遍历,单根继承。
    */
    Class superclass = c.getSuperclass();
    System.out.println(superclass.getName());
    }
    }
关于invoke的基本用法,通过这个方法,可以看下面的例子:
  1. public class InvokeDemo {
    
        private String st="invoke";
    int[] i={1,5,6,9,8,2}; public void add1(int a, int b) {
    System.out.println(a + b);
    }
    public static void add2(int a, int b) {
    System.out.println(a + b);
    }
    }
    public class InvokeTest {
    public static void main(String[] args) {
    try {
    //获取测试样例的类类型和测试实例
    Class<?> c = Class.forName("reflect.InvokeDemo");
    Object obj = c.newInstance();
    //反射调用
    Method m = c.getMethod("add1",int.class,int.class);
    int[] i={1,2};
    m.invoke(obj,i[1],i[0]);
    //没有必要通过反射调用的static方法
    InvokeDemo.add2(1, 3);
    //反射修改属性
    Field field = c.getDeclaredField("st")
    //使得这个属性可以被修改,无论它是否是私有,甚至final。
    field.setAccessible(true);
    field.set(obj, "男");
    System.out.println(field.get(obj));
    } catch (Exception e) {
    e.printStackTrace();
    } }
    }
 
输出
  1. 3
  2. 4
 
如果没有在获取Field之前调用setAccessible(true)方法,会抛出异常:
  1. java.lang.IllegalAccessException:
    Class com.test.accessible.Main
    can not access
    a member of class com.test.accessible.AccessibleTest
    with modifiers "private"
利用反射还可以做到更多的事情:
  1. public class InvokeTest2 {
    public static void main(String[] args) {
    String str = "I'm not changed!";
    change(str);
    System.out.println(str);
    } static void change(String str){
    try {
    Class<?> clazz = str.getClass();
    Field field = clazz.getDeclaredField("value");
    field.setAccessible(true);
    Object obj = field.get(str);
    char[] charValue = (char [] )obj;
    charValue = new char [str.length()];
    String st = "I'm changed!";
    charValue = st.toCharArray();
    field.set(str, charValue);
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }
这段代码违背了“java中只有副本传递”和“String类的值不可变”两个原则,可见反射真的是个很神奇也很好用的东西,但相对的,也会使代码安全性降低。

Java中反射与常用方法的更多相关文章

  1. java中String的常用方法

    java中String的常用方法1.length() 字符串的长度 例:char chars[]={'a','b'.'c'}; String s=new String(chars); int len= ...

  2. Java中反射的三种常用方式

    Java中反射的三种常用方式 package com.xiaohao.test; public class Test{ public static void main(String[] args) t ...

  3. java中反射学习整理

    转载请注明:http://blog.csdn.net/j903829182/article/details/38405735 反射主要是指程序能够訪问.检測和改动它本身的状态或行为的一种能力. jav ...

  4. Java中反射的实现方式

    所谓反射,是指在运行时状态中,获取类中的属性和方法,以及调用其中的方法的一种机制.这种机制的作用在于获取运行时才知道的类(Class)及其中的属性(Field).方法(Method)以及调用其中的方法 ...

  5. Java中String的常用方法总结

    Java中String的常用方法总结 1.length()字符串的长度 String str="HelloWord"; System.out.println(str.length( ...

  6. 简单模拟Java中反射的应用场景

    有人说Java是一门静态语言.那么何为静态语言,动态语言又是什么? 1.动态语言 是一类在运行时可以改变其结构的语言:例如新的函数.对象.甚至代码可以 被引进,已有的函数可以被删除或是其他结构上的变化 ...

  7. Java中反射机制和Class.forName、实例对象.class(属性)、实例对象getClass()的区别

    一.Java的反射机制   每个Java程序执行前都必须经过编译.加载.连接.和初始化这几个阶段,后三个阶段如下图:   其中

  8. Java中反射机制详解

    序言 在学习java基础时,由于学的不扎实,讲的实用性不强,就觉得没用,很多重要的知识就那样一笔带过了,像这个马上要讲的反射机制一样,当时学的时候就忽略了,到后来学习的知识中,很多东西动不动就用反射, ...

  9. Java 中 String 的常用方法(一)

    上一篇介绍了 String 中的几个常用构造方法,由 String 这个核心对象发散出去关于字符的编码,字符的字节表达,对 GC 的影响,正则表达式,模式匹配,这可能是 Java 里内涵最丰富的对象了 ...

随机推荐

  1. C语言高效位操作

    思考: 1. 如何将一个数据中的多个不连续位清位? 1. 如何将一个数据中的多个不连续位置位? 1. 如何反转一个数据中的多个不连续位(1->0, 0->1)? 基础知识:C 语言位操作 ...

  2. Professional C# 6 and .NET Core 1.0 - Chapter 39 Windows Services

    本文内容为转载,供学习研究.如有侵权,请联系作者删除. 转载请注明本文出处:Professional C# 6 and .NET Core 1.0 - Chapter 39 Windows Servi ...

  3. 使用 flow.ci 快速发布你的项目文档

    软件研发的协作过程中,文档是必不可少的一环,有需求文档.接口文档.使用文档等等.当开始写文档时,首先会遇到两个问题: team members 之间如何协作? 文档 OK 后如何分发,去哪里看?如何更 ...

  4. 【Zookeeper】源码分析之请求处理链(一)

    一.前言 前面已经分析了Watcher机制的主要代码,现在接着分析Zookeeper中的请求处理链,其是Zookeeper的主要特点之一. 二.总体框图 对于请求处理链而言,所有请求处理器的父接口为R ...

  5. 第一次AOP,附上使用DEMO,目前只供学习,不可用在生产环境

    GIT代码地址:https://git.oschina.net/ruanjianfeng/Ruan.Framework.Core demo代码如下 public class ConsoleTimeAt ...

  6. Python脚本收集腾讯云CDN日志,并入ELK日志分析

    负责搭建公司日志分析,一直想把CDN日志也放入到日志分析,前些日志终于达成所愿,现在贴出具体做法: 1.收集日志 腾讯云CDN日志一般一小时刷新一次,也就是说当前只能下载一小时之前的日志数据,但据本人 ...

  7. Algorithms(4th)谢路云译大纲总结(附实现源码)

    前言: 此算法书可以说是Java程序开发者的福音.里面涉及近50种计算机领域的经典算法,几位作者花了近40年的时间才完成这本著作.秉着对作者的敬仰与对算法的兴趣,我多次翻阅此书,而且常常被书中的经典算 ...

  8. http服务搭建

    http服务器搭建 主配置文件在 /etc/httpd/conf/httpd.conf 安装http  yum install httpd -y 启动http服务器  systemctl start ...

  9. UE4从零搭建CF游戏关卡(蓝图篇)

    一 往关卡中放置物体 二 Static Mesh 和 BSP 从今天开始我们要建立一个类似CF游戏的场景,不写一句代码,纯蓝图实现. 三 英语学习 今天早上开会,经理说了一件让我震惊的事情,她说最近大 ...

  10. 第26篇 jQuery 快速学习下

    前面说了下jQuery了,大部分说的都是选择器和过滤器方面的东西,这个写完后,后面就说下剩下的东西了,离目标越来越近了.下面就说说这些东西 事件 传统比较 在js中说了原生js的绑定事件,基本的形式如 ...