黑马程序员_JAVA_反射

------ Java培训、Android培训、iOS培训、.Net培训 、期待与您交流! -------

反射

类名为Class的类用来描述众多Java类的类, Class不能直接new对象。

Class cls1 = Data.class//字节码1
Class cls2 = Person.class//字节码2

先有字节码,然后由字节码生成对象, 得到字节码的3种方式:

1.类名.class
2.对象.getClass()
3.Class.forName("类名");//常用,写程序时不用明确具体的类

有9个预定义Class实例对象: 8个基本类型加一个void.class

String str1 = "abc";
Class cls1 = str1.getClass();
Class cls2 = String.class;
Class cls3 = Class.forName("java.lang.String");

cls1==cls2==cls3

同一个类的字节码文件相同

基本类中的字节码除了如int.class外,还有 Boolean.TYPE ,  Character.TYPE  ,Byte.TYPE, Short.TYPE, Integer.TYPE , Long.TYPE, Float.TYPE ,Double.TYPE , Void.TYPE

int.class !=Integer.class
int.class == Integer.TYPE

Class 类的实例表示正在运行的 Java 应用程序中的类和接口。 每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。 基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和 关键字 void 也表示为 Class 对象。

数组类型的Class实例对象: Class.isArray();判断是不是数组类型Class. 只要在源程序中出现的类型,都有各自的Class实例对象,如int[],void..。

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

Constructor类

Constructor constructor1 = String.class.getConstructor(StringBuffer.class);//获得方法时,也就是告诉选择哪一个构造方法
String str2 = (String)constructor1.newInstance(new StringBuffer("abc"));//调用获得的方法时,传递的构造函数
需要强转,因为编译时只有语法检查,不知道constructor类型, 反射会导致程序性能严重下降。

Field类

表示类中的变量的类

ReflectPoint pt1 = new ReflectPoint(3,5);//ReflectPoint中定义了两个变量,y公有,x私有
Field fieldY = pt1.getClass().getField("y");//Field表示字节码中的一个变量(相同类中的特定变量),通过方法访问具体实例对象的值
System.out.pirntln(fieldY.get(pt1));//
Field fieldX = pt1.getClass().getDeclaredField("x");//使私有X变得可见
fieldX.setAccessible(true);//使私有X变得可以访问,暴力反射
System.out.pirntln(fieldY.get(pt1));//

反射的应用

Field[] = fields = obj.getClass().getFields();//obj是形参
for(Field field : fields)
{
     //一份字节码,用“==”,因为equal也是用的"=="
     if(field.getType() == String.class)
     {
          String oldValue = (String)field.get(obj);
          String newValue = oldValue.replace('b','a');
          field.set(obj, newValue);
     }
}


Method类
(方法名字,参数类型)

Method methodCharAt = String.class.getMethod("charAt",int class);
sop(methodCharAt.invoke(str1,1)); //invoke调用(对象,参数)
对象是null,调用的是一个静态方法
sop(methodCharAt.invoke(str1,new Object[]{2}));

写程序调用main方法

class TestArguments
{
     public static void main(String[] args)
     {
          for(String arg : args)
               System.out.println(arg);
     }
}
直接调用
TestArguments.main(new String[]{"111","222","333"});
反射方式调用

问题:
启动Java程序的main方法参数是一个字符串,通过反射方式调用main方法时为invoke传递参数按照Jdk1.5,整个数组是一个参数; 按照jdk1.4语法,数组中每个元素对应一个参数,而高版本会兼容低版本,处理时会按照1.4版本将参数数组拆分如果直接传递, new String[]{"xxx"}会出现参数类型不对的错误。
解决方法:
1.将数组外再套一个数组

mainMethod.invoke(null, new Object[]{new String[]{"xxx"}});
mainMethod.invoke(null,(Object)new String[]{"xxx"});

具有相同的元素类型和相同维度的数组具有相同的Class对象

int[] a1 = new int[3];
int[] a2 = new int[4];
int[][] a3 = new int[3][4];
String[] a4 = new String[3];

a1.getClass() == a2.getClass();true
a1.getClass() == a4.getClass();false
a1,getClass() == a3.getClass();false

a1.getName()-----运算结果:[I
a1.getClass().getSuperclass().getName();求其父类名运算结果:java.lang.object
a4.getClass().getSuperclass().getName();求其父类名运算结果:java.lang.object

Object aobj1 = a1;
Object aobj2 = a2;
Object[] aobj3 = a1;//不通过
Object[] aObj4 = a3;
Object[] aObj5 = a4;

int[] a1 = new int[]{1,2,3};
String a4 = new String[3]{"a","b","c"};

System.out.println(a1);//运行结果:[I@哈希码
System.out.println(a4);//运行结果:[Ljava.lang.String;@哈希码

System.out.println(Array.asList(a1));//运行结果:[[I@哈希码]
不是object数组对象按jdk1.5当做object作为一个参数传递

System.out.println(Array.asList(a4));//运行结果:[a,b,c]
object对象按jdk1.4版本将各元素拆分传递给List

数组反射应用(打印object)

<span style="font-size:14px;">private atatic void printObject(Object obj)
{
         Class class = obj.getClass();
         if(class.isArray())
          {
               int len = Array.getLength(obj);
               for(iint i; i<len;i++)
               {
                    System.out.println(Array.get(obj,1));
               }
          }
          else
          {
               System.out,println(obj);
          }
}
</span>

如何得到数组中元素的类型?

不能直接通过a得到a的类型
int[] a = int[3];
能通过a中的元素获得元素的类型
a[0].getClass().getName();


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值