反射



反射

 

反射的基石:Class

概念:反射就是把Java类中的各种成分映射成相应的java类。

Java程序中的各个Java类属于同一类事物,描述这类实物的Java类名Class.

 

Class类代表Java类,它的各个实例对象对应各个类在内存中的字节码。例如,Person类的字节码,ArrayList类的字节码。

一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以它们在内存中的内容是不同的。这一个个的空间可分别用一个个的的对象来表示。

 

各个字节码对应的实例对象的获取:

类名.classeg:System.class

对象.getClass()eg:new Date().getClass()

Class.forName(类名)eg:Class.forName(java.util.Date

 

Class类描述的信息:类的名字,类的访问权限,类所属于的报名,字段名称的列表,方法名称的列表。

 

九个预定义Class实例对象:8种基本类型与void.

Int.class=Integer.Type

数组类型的Class实例对象

Class.isArray()

总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如:int[],void

 

反射概念:反射就是把Java类中的各种成分映射成相应的Java类。

表示Java类的Class类显然要提供一系列的方法,来获取其中的变量、方法、构造方法、修饰符、包等信息,这些信息就是用相应类的实例对象来表示。它们是FieldMethodConstructorPackage等。

一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象。

 

Constructor:Constructor类表示某个类中的一个构造方法。

获取某个类所有的构造方法:

Eg:Constructor [] constructors=Class.forName(java.util.String).getConstructors();//获得方法时要用到类型

获取某一个构造方法:

Eg:Constructor constructor=Class.forName(java.util.String).getConstructor(StringBuffer.class);

创建实例对象:

通常方法:String str=new String(new StringBuffer(abc));

反射方法:String str=(String)constructor.newInstance(new StringBuffer(abc));

//调用获取的方法要用到上面相同类型的实例对象

Class.newInstance()方法:

Eg:String str=(String)Class.forName(java.lang.String).newInstance();该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。//class----construcot----new object

 

Field类:Field类表示某个类中的一个成员变量

Eg:

Field field=pt.getClass().getField("y");//field不是对象身上的变量,而是类身上的变量

System.out.println(field.get(pt));//取值,即y得值

 

 

Mehtod:Method类代表某个类的一个成员方法

获取类中的某个方法:

Eg:Method charAt=Class.forName(java.util.String).getMethod(charAt,int.class);

调用方法:

通常方法:System.out.println(str.charAt(1));

反射方法:System.out.println(charAt.invoke(str,1));

如果传递给Method对象的invoke()方法的一个参数为null,说明Method对象对应的是一个静态对象

 

JDK1.4JDK1.5invoke方法的区别:

JDK1.5:public Object invoke(Object obj,Object...args)

JDK1.4:public Object invoke(Object obj,Object[]aegs)

 

数组的反射:

具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。

代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class

基本类型的一维数组可以当作Object类型使用,不能当作Object[]类型使用;非基本类型的一维数组,即可以当作Object类型使用,又可以当作Object[]类型使用。

 

实例:

package cn.itcast.day1;

public class ReflectPoint {

private int x;//定义私有变量x

public int y;//定义公有变量

//定义字符串str1,str2,str3

public String str1="ball";

public String str2="basketball";

public String str3="itcast";

//构造函数

public ReflectPoint(int x, int y) {

super();

this.x = x;

this.y = y;

}

public String toString()

{

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

}

}


package cn.itcast.day1;

import java.lang.reflect.Constructor;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

import java.util.Arrays;

 

public class ReflectTest {

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

{

//定义字符串str1

String str1="abc";

//实例对象获取的三种方法

Class cls1=str1.getClass();

Class cls2=String.class;

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

System.out.println(cls1==cls2);//true,表示同一个字节码

System.out.println(cls1==cls3);//true,表示同一个字节码

System.out.println(cls1.isPrimitive());//是不是原始类型false

System.out.println(int.class.isPrimitive());//是不是原始类型true

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

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

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

//总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如int[],void

//获取构造函数

Constructor<String> constructor=String.class.getConstructor(StringBuffer.class);

//获取实例对象

String ss=(String)constructor.newInstance(new StringBuffer("abc"));

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

ReflectPoint pt=new ReflectPoint(3,5);

//获取成员变量

Field field=pt.getClass().getField("y");//field不是对象身上的变量,而是类身上的变量

System.out.println(field.get(pt));//取值,即y得值

Field field1=pt.getClass().getDeclaredField("x");//因为x为私有变量,所以用getDeclaredField()方法

field1.setAccessible(true);//暴力反射

System.out.println(field1.get(pt));//取值,即x的值

changeStringValue(pt);

System.out.println(pt.toString());

//Method

//通常方法str1.charAt();

Method method=String.class.getMethod("charAt",int.class);//第一个参数是方法名

System.out.println(method.invoke(str1, 1));//JDK1.5invoke()方法

System.out.println(method.invoke(str1, new Object[]{2}));//JDK1.4invoke()方法

 

/*

通常方法:

Test.main(new String[]{});

Test.main(new String[]{"111","222"});*/

//调用Testmain()方法

String ss1="cn.itcast.day1.Test";

Method method1=Class.forName(ss1).getMethod("main",String[].class);

System.out.println(method1.invoke(null, new Object[]{new String[]{"111","222"}}));

//数组的反射

int[] a1=new int[3];

int[] a2=new int[4];

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

String[] a4=new String[3];

System.out.println(a1.getClass()==a2.getClass());//true

System.out.println(a1.getClass().equals(a3.getClass()));//false

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

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

Object obj1=a1;

Object obj4=a4;

Object[] obj3=a3;

Object[] obj5=a4;

//Arrays.asList()方法处理int[]String[]的不同

System.out.println(Arrays.asList(a1));//[[I@1690726]

System.out.println(Arrays.asList(a4));//[null, null, null]

 

 

}

////将任意一个对象中的所有String类型的成员变量所对应的字符串内容的"b"改成"a"

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 oldString=(String)field.get(obj);

String newString=oldString.replace('b','a');

field.set(obj, newString);

}

}

}

}

class Test{

public static void main(String[]args)

{

for(String arg:args)

{

System.out.println(arg);

}

}

}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值