黑马程序员——反射

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

Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。

有时候我们说某个语言具有很强的动态性,有时候我们会区分动态和静态的不同技术与作法。我们朗朗上口动态绑定(dynamic binding)、动态链接(dynamic linking)、动态加载(dynamic loading)等。然而“动态”一词其实没有绝对而普遍适用的严格定义,有时候甚至像面向对象当初被导入编程领域一样,一人一把号,各吹各的调。

一般而言,开发者社群说到动态语言,大致认同的一个定义是:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,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如何能够做出上述的动态特性呢?这是一个深远话题,本文对此只简单介绍一些概念。整个篇幅最主要还是介绍Reflection APIs,也就是让读者知道如何探索class的结构、如何对某个“运行时才获知名称的class”生成一份实体、为其fields设值、调用其methods。本文将谈到java.lang.Class,以及java.lang.reflect中的Method、Field、Constructor等等classes。package cn.itcast.com;

import java.lang.reflect.Array;

import java.lang.reflect.Constructor;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

import java.util.Arrays;

public class ReflectText {

/**

* @param args

*/

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

// TODO Auto-generated method stub

String str1 =  "abc";

Class cls1 = str1.getClass();

Class cls2 = String.class;

Class cls3 = Class.forName("java.lang.String");

System.out.println(cls1==cls2);

System.out.println(cls1==cls2);

System.out.println(cls1.isPrimitive());//cls1是否是基本类型字节码false  String非基本类型

System.out.println(int.class.isPrimitive());//true

System.out.println(int.class==Integer.class);//flse

System.out.println(int.class==Integer.TYPE);//true

System.out.println(int[].class.isPrimitive());//false

System.out.println(int[].class.isArray());//ture

/*得到某个类的所有构造方法

* Constructor[] constructors = Class.forName("类名").getConstructors();

*/

//编译器只看代码的定义

//得到String的构造方法夸号里的是该构造方法的参数,说明是返回这个构造方法字节码

Constructor constructor1 = String.class.getConstructor(StringBuffer.class);

String str5 = (String)constructor1.newInstance(new StringBuffer("abc"));

System.out.println(str5.charAt(2));

ReflectPoint pt1 = new ReflectPoint(3,5);

Field fieldY = pt1.getClass().getField("y");

//fieldY是对应是类上的变量而 不是不是对应某个指定对象上的变量!!!

System.out.println(fieldY.get(pt1));//取出pt1对应的fieldY值=5

//y是共有的,而x是私有的要改变访问方法

Field fieldX = pt1.getClass().getDeclaredField("x");

//能访问但不能读取值

fieldX.setAccessible(true);

System.out.println(fieldX.get(pt1));

changeStringValue(pt1);

System.out.println(pt1);

//Method类中的方法

//用字节码得到String中的charAt方法再去作用str1这个对象

//str1.charAt(1);

//String对象下的charAt方法charAt方法的参数是int

//methodCharAt是一个方法对象

Method methodCharAt = String.class.getMethod("charAt", int.class);

//用反射机制得到字节码中某个方法,再用这个方法去作用这个对象

//用methodCharAt方法对象去调用(invoke)这个方法(charAt)

//如果invoke第一个参数是null则他调用的是静态方法

System.out.println(methodCharAt.invoke(str1,2));

//在程序中直接用静态的方式调用main方法

TestArguements.main(new String[]{"111","222","333"});

//用反射机制来调用main

String startingClassName = args[0];

Class clazz = Class.forName(startingClassName);

Method mainMethod = clazz.getMethod("main", String[].class);

//Method mainMethod = Class.forName(startingClassName.getClass().getMethod("main",String[].class));

//mainMethod.invoke(null,new String[]{"111","222","333"});

//上面这种方法不行,虽然是一个字符串数组,但jdk1.5把他拆开看做3个,就有3各参数,与main的参数个数不一致

mainMethod.invoke(null,new Object[]{new String[]{"111","222","333"}});//封装成一个对象数组

int[] a1 = new int[]{1,2,3};

int[] a2 = new int[4];

int[][] a3 = new int[2][3];

String[] a4 = new String[]{"a","b","c"};

System.out.println(a1.getClass() == a2.getClass());//ture同一类型的字节码  int  且一维

//System.out.println(a1.getClass() == a4.getClass());//false

//System.out.println(a1.getClass() == a3.getClass());

System.out.println(a1.getClass().getName());//[I  说明是整型

System.out.println(a1.getClass().getSuperclass().getName());//java.lang.Object

System.out.println(a4.getClass().getSuperclass().getName());//java.lang.Object

/*Object可以引用任何的类,像int double char这类是基本类型,Object不能引用,

* 但是可以引用他们的封装类,Integer Double这种,

* 因此,Object数组能放除了8个基本类型之外的所有类

* */

Object Obj1 = a1;

Object Obj2 = a4;

//Object[] Obj3 = a1;//不对  a1是一维数组,里面每个元素师基本数据类型

//String对象类型,二维数据分为一维数组装了几个一维数组,其中一维数组是对象

Object[] Obj4 = a3;

Object[] Obj5 = a4;

System.out.println(a1);

System.out.println(a4);

//Arrays.asList(对象类型)

System.out.println(Arrays.asList(a1));//整数不打印出每个元素,把所有数据看做一个内容

System.out.println(Arrays.asList(a4));//打印出每个元素

printObject(a4);// a回车b回车c

printObject("xyz");//xyz

}

private static void printObject(Object obj){

Class clazz = obj.getClass();

if(clazz.isArray()){

int len = Array.getLength(obj);

for(int i=0;i<len;i++){

System.out.println(Array.get(obj, i));

}

}else{

System.out.println(obj);

}

}

private static void changeStringValue(Object obj)throws Exception {

// TODO Auto-generated method stub

Field[] fields = obj.getClass().getFields();

for(Field field : fields){

//不能写field.getType().equals(String.class)

//虽然正确但字节码只有一份肯定比较的是地址,上面的有语义错误

if(field.getType() == String.class){

String oldValue = (String)field.get(obj);

String newValue = oldValue.replace(‘b‘, ‘a‘);

field.set(obj, newValue);

}

}

}

}

class TestArguements

{

public static void main(String[] args){

for(String arg : args){

System.out.println(arg);

}

}

}

package cn.itcast.day1;

import java.util.Date;

public class ReflectPoint {

private Date birthday = new Date();

private int x;

public int y;

public String str1 = "ball";

public String str2 = "basketball";

public String str3 = "itcast";

public Date getBirthday() {

return birthday;

}

public void setBirthday(Date birthday) {

this.birthday = birthday;

}

public int getX() {

return x;

}

public void setX(int x) {

this.x = x;

}

public int getY() {

return y;

}

public void setY(int y) {

this.y = y;

}

public ReflectPoint(int x, int y) {

super();

this.x = x;

this.y = y;

}

public String toString(){

return str1+":"+str2+":"+str3;

}

@Override

public int hashCode() {

final int prime = 31;

int result = 1;

result = prime * result + x;

result = prime * result + y;

return result;

}

@Override

public boolean equals(Object obj) {

if (this == obj)

return true;

if (obj == null)

return false;

if (getClass() != obj.getClass())

return false;

ReflectPoint other = (ReflectPoint) obj;

if (x != other.x)

return false;

if (y != other.y)

return false;

return true;

}

}

详情请查看:http://edu.csdn.net/heima

时间: 2024-10-11 10:59:52

黑马程序员——反射的相关文章

黑马程序员——反射总结

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 什么是反射? 毕老师说“万物皆对象”,每个Java类可以构成一个对象,同时每个Java类也可以由一个Class类封装成对象,反射就是把类中的成员变量,构造函数,方法,包都封装成类,在封装的类中,操作类和类中的成员. 为什么要用反射? 在框架结构中反射用的最多,这就像生产一部汽车,我们这里有一副汽车构造图,而轮子,车身,发动机等车的部件通过不同的部门生产出来,最后装配在一起,实现了流水线高效率的

黑马程序员——反射机制

------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! ------- 反射机制 下面我们一起来探讨一下java的反射机制吧!功能太强大了,哈哈!  (一).  定义 Reflection(反射)是Java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并

黑马程序员------反射机制

------- android培训.java培训.期待与您交流! ---------- 1.1 反射机制 * JAVA反射机制是在运行状态中,对于任意一个类 (class文件),都能够知道这个类的所有属性和方法: * 对于任意一个对象,都能够调用它的任意一个方法和属性: * 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. * * *反射其实就是动态加载一个指定的类,并获取该类中的所有的内容. *而且将字节码文件封装成对象,并将字节码文件中的内容都封装成对象,这样便于操

黑马程序员——反射实战

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- [案例1]通过一个对象获得完整的包名和类名 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package Reflect; /**  * 通过一个对象获得完整的包名和类名  * */ class Demo{     //other codes... } class hello{     public static void main(String[] args) {

黑马程序员—反射篇

--Java培训.Android培训.iOS培训..Net培训.期待与您交流! -- 1:获取字节码的三种方式: Employee emp=new Employee(); Class clazz1=Employee.class; Class clazz2=Class.forName("java.util.HashSet"); Class clazz3=emp.getClass(); 2:通过字节码获取对象: Employee enp=(Employee) clazz2.newInsta

黑马程序员——高新技术---反射

黑马程序员——高新技术---反射 ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------ 一.概述 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 反射把Java类中的各种成分映射成相应的Java类,例如一个Java类中用一个Class类的对象表示,一个类中的组成部分:成员变量,方法,构造方

黑马程序员_Java反射机制

一切的操作都将使用Object完成,类,数组的引用都可以使用Object来接收 1,认识Class类 以前要是想知道一个类中的属性,成员变量,方法等等的信息的话,需要通过new这个类的对象才能得到这些信息,但是在Java中,也允许一个实例化对象找到一个类的完整的信息,这个类就是Class类,Class类是继承Object类的. 正常方式:  引入需要的"包.类"名称 >取得实例化对象 反射方式:  实例化对象>得到完整的"包.类"名称 getClass(

黑马程序员——java基础——反射

 黑马程序员--java基础--反射 ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 反射 其实就是动态加载一个指定的类,并获取该类中的所有的内容.而且将字节码文件封装成对象,并将字节码文件中的内容都封装成对象,这样便于操作这些成员. 反射就是把Java类中的各种成分映射成相应的java类. 简单说:反射技术可以对一个类进行解剖. 反射的基石-->Class类 1.java中的类是用来描述一类事物的共性,该类事物有什么属性,没有什么属性

黑马程序员_高新技术_1_Java反射

------- android培训.java培训.期待与您交流! ---------- 0.反射知识体系 下图为反射整体的知识体系,把握住此图也就全局上掌握住反射所有内容. 1.反射概论 1)反射概念 其实字面上可以这么理解反射,平时使用类时都是由类new出对象,而反射则是通过对象"反射"出类的信息,好比一个人照镜子可以看到人类的特征,而看出机制就是镜子反射. 2)Java对象两种类型 Java程序中的许多对象在运行时会出现两种类型:编译时类型和运行时类型.如下代码: Person p