在JVM中对一个类实例的创建,有两种方式,一种是编译时,一种是运行时。两种方式在开发过程中都是十分重要的。在Java中无时无刻无处不在的Java对象,实例化的过程也就变得尤为引人瞩目。我们经常用new Object()方法来创建实例,而相反的,反射在这个时候就显得突兀,因为有人就会问,Java对象实例的时候为什么不直接new Object就好了呢?其实是情况所迫,有些时候,我们在编译的时候并不知道要什么对象,这个对象的字节码也不知道存在什么地方?是在硬盘,内存,还是遥远的世界另一端的一台电脑中,所以,我们这个时候就用另外一种婉转地方式去编写。

 
分析


       一个类中有不同的portion,而Field(属性),Constructor(构造器),Method(方法)三大重要的部分。我们对一个类的操作也无非就对这个三个部分进行invoke而已。所以通过反射,我们拿到这些attribute用来操作。
       同时我们也要了解,既然在Java中一切皆为对象,那么一个类中的组成部分也是可以单独被拿出来作为各自不同的对象来着。这样子有利于我们对象思维的理解和简单化编写代码。
 
  • 字节码的理解
  • Construtor
  • Field
  • Method
  • Array数组和Object的关系
  • 创建newInstance对象
 

 
 
 
实例讲解

字节码的理解
一切对象在JVM中,在计算机的内存中,在计算机的硬盘中,其实都是以二进制的形式存在。那么我们去理解Java中的字节码,仔细一想,也不就是二进制的内容形式存在于电脑中吗?对的,那么这个时候去了解这个部分,其实就简单得多了。无论是String,Integer,还是Char,说到底就是一段杂乱无序的0011而已。我们忽略掉这个貌似繁杂的部分去看真实的问题所在,说到底,就是一叠数据和符号而已。
 
  1.  String str1 ="abc";
    Class cls1 = str1.getClass();
    Class cls2 =String.class;
    Class cls3 =Class.forName("java.lang.String");
    System.out.println(str1.getClass());
    System.out.println(cls1 == cls2);
    System.out.println(cls3 == cls2);
    /**
    输出结果
    class java.lang.String
    true
    true
    */
 
String的一个实例是str1,所以str1的class就是java.lang.String 所以我们发现String.class和通过Class.forName("java.lang.String")去得到一个Class其实都是String在JVM中的Class。
除此之外,还有一些有关于Class这个类的方法(一切皆为对象,对象本身也是一个对象,有属于自己的特性)
  1.  System.out.println(int[].class.isPrimitive());
    System.out.println(int[].class.isArray());
 
Construtor
        一个类首先要有一个无参的构造方法,其次有可能有有参的构造方法。同时我们知道方法的overload,其中最主要去区别就是参数的个数和类型的不同。那么Construtors也可能有多个构造方法,于是Java就提供了拿到具体的构造方法,或者拿到所有的构造方法。
  1. //得到全部的构造方法
    //constructor
    Constructor[] constuctor =Class.forName("java.lang.String").getConstructors();
    //得到参数为StringBuffer的构造方法
    Constructor constructor =Class.forName("java.lang.String").getConstructor(StringBuffer.class);
Field
       类所拥有的属性,private或者public的。我们要得到所有的Field,可能在private属性的情况下,就需要通过getDeclaredField和setAccessible来获取这个属性了。
public class ReflectPoint{
//private和public的属性
private int x;
public int y;
public ReflectPoint(int x,int y){
super();
this.y = y;
this.x = x;
}
publicString toString(){
System.out.println(str1 + str2 + str3);
return str1 + str2 + str3;
}
}
//Field
ReflectPoint pt1 =newReflectPoint(3,5);
Field fieldY = pt1.getClass().getField("y");
System.out.println(fieldY.get(pt1));
Field fieldX = pt1.getClass().getDeclaredField("x");
fieldX.setAccessible(true);
System.out.println(fieldX.get(pt1));
/**
结果:
5
3
*/
  1.         
 
由此可以知道其实private和public的属性是需要通过不同的方法才可以拿到的。 
同时这个我们可以通过反射拿到Field的值,然后再将值改变。调用下面的方法,会将传入的Object中的属性中的值,将含有a都替换成b

private static void changeStringValue(Object obj) throws Exception{
// TODO Auto-generated method stub
Field[] fields = obj.getClass().getFields();
for(Field field : fields){
if(field.getType()==String.class){
String oldValue =(String) field.get(obj);
String newValue = oldValue.replace("a","b");
field.set(obj, newValue);
}
}
}
 
Method
其实拿到一个类中方法,和构造方法其实是一样的,第一个参数就是方法名,第二个参数就是这个方法的传入参数的类型,如果还有更多的参数,也可以继续写进去的。
  1. //Method方法
    String str1 = "a";
    Method methodCharAt =String.class.getMethod("charAt",int.class);
    System.out.println(methodCharAt.invoke(str1,1));
    //str1是一个String的实例对象

      

同时方法的启动是用invoke的第一参数是含有这个方法的类的一个实体。第二个参数则是这个方法的要传入的各种参数的真实数据啦。当然,有时候静态方法static实际是不需要实例对象的,因为在java运行的时候就将这些静态方法的实例都存在JVM中了,所以invoke可以是null,invoke(null, new Object[]{new String[]{"111","222","333"}});
 
 
Array数组和Object的关系
        一个Object可以是什么类型呢?我们知道所有的类都是以Object为父类,但是数组呢?String不是Java的8大数据类型,String的父类是Object,但是Java中8大数据类型(boolean,byte,char,short,int,float, long,double)其实对应的Java类分别为(Boolean, Byte , Character ,Short , Integer , Float , Long ,Double)这些封装类的父类才是Object,他们本身不是,所以,我们在数组中保存这些数据类型的时候就是数组就是一个Object,但是String的数组可以用Object[] 来表示。

       讲了那么多,我们才可以用数组的反射做事情。

/**
* 数组的反射
* @param o1
*/
private static void printObject(Object o1){
// TODO Auto-generated method stub
Class clazz = o1.getClass();
if(clazz.isArray()){
int length =Array.getLength(o1);
for(int i =0; i < length; i++){
System.out.println(Array.get(o1, i));
}
}else{
System.out.println(o1);
}
} int[] a1 =newint[]{1,2,3};
int[] a2 =newint[4];
int[][] a3 =newint[3][4];
String[] a4 =newString[]{"a","b","c"};
printObject(a1);
printObject(a4);
注意这里,String的数组即可以用Object来表示,也是可以用Object[]来表示的,但是int[]的数组却只能用Object来表示,不能用Object[]来表示。
 
创建newInstance对象
这个就比较简单啦,通过得到一个Class对象,再将其newInstance化。
  1. String obj =(String)Class.forName("java.lang.String").newInstance();

结束:我们知道真正地改变是在不断地练习中成长的。(文不对题哈哈)

Java反射深入浅出(一)的更多相关文章

  1. Java反射深入浅出

    在JVM中对一个类实例的创建,有两种方式,一种是编译时,一种是运行时.两种方式在开发过程中都是十分重要的.在Java中无时无刻无处不在的Java对象,实例化的过程也就变得尤为引人瞩目.我们经常用new ...

  2. 深入浅出Java反射

    反射,它就像是一种魔法,引入运行时自省能力,赋予了 Java 语言令人意外的活力,通过运行时操作元数据或对象,Java 可以灵活地操作运行时才能确定的信息 这里笔者就深入浅出总结下Java反射,若有不 ...

  3. 第28章 java反射机制

    java反射机制 1.类加载机制 1.1.jvm和类 运行Java程序:java 带有main方法的类名 之后java会启动jvm,并加载字节码(字节码就是一个类在内存空间的状态) 当调用java命令 ...

  4. Java反射机制

    Java反射机制 一:什么事反射机制 简单地说,就是程序运行时能够通过反射的到类的所有信息,只需要获得类名,方法名,属性名. 二:为什么要用反射:     静态编译:在编译时确定类型,绑定对象,即通过 ...

  5. java反射(基础了解)

    package cn.itcast_01; /** *Person类 */ public class Person {    /** 姓名 */    private String name;     ...

  6. java基础知识(十一)java反射机制(上)

    java.lang.Class类详解 java Class类详解 一.class类 Class类是java语言定义的特定类的实现,在java中每个类都有一个相应的Class对象,以便java程序运行时 ...

  7. java基础知识(十一)java反射机制(下)

    1.什么是反射机制? java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象都能够调用他的属性和方法,这种动态获取属性和方法的功能称为java的反射机制. ...

  8. java反射学习之二万能EXCEL导出

    一.EXCEL导出的实现过程 假设有一个对象的集合,现在需要将此集合内的所有对象导出到EXCEL中,对象有N个属性:那么我们实现的方式是这样的: 循环这个集合,在循环集合中某个对象的所有属性,将这个对 ...

  9. java反射学习之一反射机制概述

    一.反射机制背景概述 1.反射(reflection)是java被视为动态语言的一个关键性质 2.反射机制指的是程序在运行时能获取任何类的内部所有信息 二.反射机制实现功能概述 1.只要给定类的全名, ...

随机推荐

  1. 链式前向星+SPFA

    今天听说vector不开o2是数组时间复杂度常数的1.5倍,瞬间吓傻.然后就问好的图表达方式,然后看到了链式前向星.于是就写了一段链式前向星+SPFA的,和普通的vector+SPFA的对拍了下,速度 ...

  2. 【BZOJ1067】【POJ2637】降雨量

    1067: [SCOI2007]降雨量 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 3004  Solved: 767[Submit][Status] ...

  3. iOS 自动布局小结

    1> sizeclasses 可以限制某个 storyboard 显示在什么样的屏幕上,如 当前 storyboard 在iPhone 的左斜右斜或 iPad上是否显示.. 2> Hug值 ...

  4. Crystal Reports 2008(水晶报表) 安装

    这篇blog主要是介绍Crystal Reports2008(水晶报表)的安装. 首先我们应该知道Crystal Reports 有什么作用? 从这里Crystal Reports 你可以了解到它的一 ...

  5. C# 非模式窗体show()和模式窗体showdialog()的区别(转)

    对话框不是模式就是无模式的.模式对话框,在可以继续操作应用程序的其他部分之前,必须被关闭(隐藏或卸载).例如,如果一个对话框,在可以切换到其它窗 体或对话框之前要求先单击“确定”或“取消”,则它就是模 ...

  6. JS文档生成工具:JSDoc 介绍

    JSDoc是一个根据javascript文件中注释的信息,生成API文档的工具.生成的文档是html文件.类似JavaDoc和PHPDoc. 用法 /** 一坨注释之类的 */JSDoc会从/**开头 ...

  7. JSch - Java实现的SFTP(文件下载详解篇)

    上一篇讲述了使用JSch实现文件上传的功能,这一篇主要讲述一下JSch实现文件下载的功能.并介绍一些SFTP的辅助方法,如cd,ls等. 同样,JSch的文件下载也支持三种传输模式:OVERWRITE ...

  8. Bone Collector(01背包)

    题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=87125#problem/N 题目: Description Many year ...

  9. css解决select下拉表单option高度的办法

    css在给select下拉表单设置样式如边框时可以轻松搞定,而我们在不喜欢其默认的下拉箭头的样式时试图通过background:url(图片路径)来修改之,则往往会出现浏览器的兼容性问题,在网上查了好 ...

  10. mysql 的2个关于事务和安全性的参数

    innodb_flush_log_at_trx_commit:(mysql写事物日志的方式) 0 log buffer 会每秒写入到日志文件中,并刷新到磁盘  (提交方式与事物无关,性能最好) 1 事 ...