黑马程序员技术交流社区

标题: 关于字节码的一点疑惑(急!) [打印本页]

作者: 孔肖    时间: 2012-9-23 16:19
标题: 关于字节码的一点疑惑(急!)
本帖最后由 孔肖 于 2012-9-23 18:01 编辑

这个方法是将任意对象中的所有String字段中的'b'-->'B'
疑惑的地方用红色标出了,请各位能讲的简单详细深入一点!谢谢!

public static void changeStringValue(Object obj) throws Exception
{
         Field[] fields = obj.getClass().getFields();
  
        for(Field field : fields)
       {   
             // 张老师说这里是同一份字节码,我的疑惑是获取到的字节码和String类的字节码在内存中时如何存放的,对于 "=="的比较又是如何比较的?
             if(field.getType() == String.class)
            {
                  // 这里要注意类型转换 obj --> String,上面已经比较了类型,为什么这里还要类型转换?
                  String oldValue = (String)field.get(obj);
                  String newValue = oldValue.replace('b', 'B');
                 field.set(obj, newValue);
             }
      }
}

作者: 赵永康    时间: 2012-9-23 16:35
field.getType() == String.class  这句话的意思就是判断你所获取的是不是String类型的,因为一个类中的字段可能有很多,至于用==号就是因为字符串属于常量池中的元素。 所以不用equals。。用equals方法也能通过,但是==会显得更专业点

String oldValue = (String)field.get(obj); filed的get()方法返回值就是Object类型的,他得到指定对象上的字段还不能够确定,也有可能int等 都不一样的
所以,要进行强转

作者: 王海宇    时间: 2012-9-23 16:56
一个类首先要被Java虚拟机装载到内存里面才能使用,String类也不例外。Java虚拟机将String.class文件从硬盘读取到内存里面,经过一系列处理后就变成了字节码。要注意的是,任何一种数据类型(例如String、int)所对应的Class实例对象在内存里面只保存一份,也就是说无论我们以什么样的形式获取Class实例对象,只要是它们所对应的数据类型相同,那它们的引用地址也相同。举个例子:
  1. Class clazz1 = String.class;
  2. Class clazz2 = new String("").getClass();
复制代码
以上两种获取Class实例对象clazz的方法很不相同,但是它们最终获取到的Class实例其实是同一个,也就是clazz1和clazz2都指向内存里面同一份字节码,就是因为无论是clazz1还是clazz2,它们的字节码所对应的数据类型都是String类型。
因此,你的问题中,if语句的判定条件的意思就是当field.getType()的返回结果是String.class时(“==”就是比较两个对象的引用是否相等,说白了就是看两个对象是否是同一个),也就是说field里面封装的数据的真实类型是String类型时,就执行if语句。
之所以要在下面进行强制类型转换,是因为替换字符的方法replace()是String类所拥有的,field.get(obj)返回的是Object类型的数据,不含replace方法,而编译器在编译阶段是无法确定field.get(obj)返回值的真实类型的,因此需要用强制转换告诉编译器field.get(obj)所返回的对象是就是String类型的,好让编译器通过,而我们也就可以在后面使用replace()方法了
作者: 尤圣回    时间: 2012-9-23 17:19
equals比较的是让内容是否相同 而==表示是否指向同一个对象
作者: 怪盗急得    时间: 2012-9-23 17:30
本帖最后由 陈德基 于 2012-9-23 17:33 编辑

反射。就是将java类中的各个成分(class类的实例对象)映射到相应的java类上,这个是张老师视频里的引用,加了点我自己的理解,

getClass();通过这个方法能得到该类在内存中的字节码(已经在内存中,是唯一的)。

举个例子:
String str1 = "abc";

Class cls1 = str1.getClass();

Class cls2 = String.class;

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

sop(cls1 == cls2);  true
sop(cls1 == cls3);  true
上面两个答案就说明了,引用变量指向的都是内存中同一份字节码。

至于用equals方法来比较,其实也是一样的,假设比较的是两个对象,这里面的两个对象字节码相同,自然就返回true。何况指向的都是同一个对象呢?

还有为什么要向下转型的问题,是因为getClass()方法返回的类型是Object类型,在帮助文档里有明确说明。

作者: 杜正华    时间: 2012-9-23 19:50
package cn.itcast.day1;

public class Practise {

        /**
         * @param args
         */
        public static void main(String[] args) {
                // TODO Auto-generated method stub
                String s1 = "abc";
                String s2 = new String("abc");
                System.out.println(s1.equals("abc"));  //true
                System.out.println(s1.equals(s2));  //true
               
                System.out.println(s1 == s2);  //false

        }

}

由此可见equal函数比较的是对象在内存中的内容,因为s1与s2内存中的内容都是abc所以返回true。 ==比较的是内存中的内容和地址,因为s1与s2内容相同但是内存地址不同所以返回false




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2