黑马程序员技术交流社区

标题: 答题送分,快来参加吧! [打印本页]

作者: lwj123    时间: 2015-2-6 09:49
标题: 答题送分,快来参加吧!
本帖最后由 lwj123 于 2015-2-8 00:03 编辑

答题送分活动一
我们在学习Java基础时,有些知识点是我们没有注意到的,例如:
举例一:
FileInputStream(String filePath)
FileInputStream(File file)
第一个构造的源码其实也是将filePath封装成File对象

举例二:
ByteArrayStream这个流中的close()方法写不写都是无所谓了,源码中这个方法也是没有方法体的

举例三:
有个集合中存储的数据类型是字符串,我们一般都写一个比较器去对这些字符串进行比较字符串长度之类的,但是有些人想为什么不去重写String中compareTo方法?
在API中我发现String是final修饰的,根本就无法去继承,更谈不上重写了。

举例四:
观察集合中contains方法源码,其实底层调用的equals方法


举例五:
Properties是Map体系的,但是Properties却不是泛型类。

其他的,等你们来写...

这些细枝末节的东西我们可能没去注意到,但是理解了这些东西,有助于我们的学习更加深入。

答题规则:
       写出你在学习中观察源码或者API之后发现的一些跟上面举例类似有趣东西,分享给我们,回帖比较好的有技术分送哦!
       还有强调一点不要有水贴,否则"关小屋"。


本人技术有限,以上例子若是有错误,你们可以向我提出qq:2905090240
活动还会继续,敬请期待...



作者: Gonnaloveu    时间: 2015-2-6 10:12
我感觉现在已经沦陷了,完全是水军的天下,问问题的没人回答,只有一堆复制粘贴和一些问题不过脑子混黑马币的,我都不想来了..
作者: 万合天宜    时间: 2015-2-6 10:23
感觉好深奥的样子啊,楼楼厉害啊
作者: 邓士林    时间: 2015-2-6 11:05
还是说说==和equals,因为今天我才明白。
【==是比较对象的时候比较内存,equals底层也是用==实现】这句话,相信大家都看过,对于后半句话,说的不全,今天就给大家说说我的理解。
还是先看例子:
  1.         String str1 = "abc";
  2.                 String str2 = "abc";
  3.                 System.out.println("str1-->" + str1.hashCode());
  4.                 System.out.println("str2-->" + str2.hashCode());
  5.                 System.out.println(str1 == str2);
  6.                 System.out.println(str1.equals(str2));
  7.                 ---------- 运行 ----------
  8.                 str1-->96354
  9.                 str2-->96354
  10.                 true
  11.                 true
  12.                 输出完成 (耗时 0 秒) - 正常终止
复制代码
不难理解,二者内存比较都相同,所以equals自然返回true。
  1. String str1 = new String("abc");
  2.                 String str2 = new String("abc");
  3.                 System.out.println("str1-->" + str1.hashCode());
  4.                 System.out.println("str2-->" + str2.hashCode());
  5.                 System.out.println(str1 == str2);
  6.                 System.out.println(str1.equals(str2));
  7.                 ---------- 运行 ----------
  8.                 str1-->96354
  9.                 str2-->96354
  10.                 false
  11.                 true
  12.                 输出完成 (耗时 0 秒) - 正常终止
复制代码
这个例子,内存都不相同,equals咋还返回true了呢?
我们看看String类的equals源码:
  1. public boolean equals(Object anObject) {
  2.         if (this == anObject) {
  3.             return true;
  4.         }
  5.         if (anObject instanceof String) {
  6.             String anotherString = (String)anObject;
  7.             int n = count;
  8.             if (n == anotherString.count) {
  9.                 char v1[] = value;
  10.                 char v2[] = anotherString.value;
  11.                 int i = offset;
  12.                 int j = anotherString.offset;
  13.                 while (n-- != 0) {
  14.                     if (v1[i++] != v2[j++])
  15.                         return false;
  16.                 }
  17.                 return true;
  18.             }
  19.         }
  20.         return false;
  21.     }
复制代码
源码解析:
1、先进行地址比较==(针对任何对象),如果地址相同返回true,如果地址不同,则继续向下
2、判断是否是String 类对象,不是返回false。
3、是String 类对象,则比较它们的值,值相同还是会返回true。
这就是为什么第二例子返回true的原因了,不看源码以前还真不知道,今天才晓得啊!我也是看别人说equals底层就是==实现,今天一看,还是有点区别的。高手勿喷啊!



作者: xiaoyi    时间: 2015-2-6 18:11
浮点类型的数可以被0除,
运行结果是  Infinity无限大
作者: lwh316658735    时间: 2015-2-6 18:43
来个简单的把
分析源码  set集合的底层是采用map集合实现的,在实现过程中将所有value值设置为Object对象
对于TreeSet的排序就是在TreeMap的基础上排序然后封装起来。
作者: love$$-IT    时间: 2015-2-6 18:58
观察源代码:增强for,底层其实就是通过迭代器来实现的。
通过迭代器来实现hasNext(),next(),rmove()等方法。
作者: q243539594    时间: 2015-2-6 19:22
Java是跨平台的
作者: kenfine    时间: 2015-2-6 20:52
q243539594 发表于 2015-2-6 19:22
Java是跨平台的

补充:Java跨平台的原理就是JVM不跨平台!Java依赖的是不同操作系统里面的不同JVM来调用操作系统资源的!(JVM:Java 虚拟机)
作者: lwj123    时间: 2015-2-6 21:59
实现集合类线程安全的方法如下:
List<String> list = Collections
                                .synchronizedList(new ArrayList<String>());:这样可以使用List集合编程线程安全的

Map<String, String> map  = Collections.synchronizedMap(new HashMap<String,String>());
将Map集合编程线程安全的。

这就是我们不会去使用线程安全的Vector集合类的原因了。

自个顶一下!!!
作者: 610757257    时间: 2015-2-6 22:42
注意:collectionXxx.java使用了未经检查或不安全的操作.
注意:要了解详细信息,请使用 -Xlint:unchecked重新编译.
java编译器认为该程序存在安全隐患


温馨提示:这不是编译失败,所以先不用理会,等学了泛型你就知道这是怎么一回事

有人遇到过以为是报错的吗???
作者: qiuyuhuaihua    时间: 2015-2-6 22:57
Java 中的参数传递 值传递?or 引用传递?

作者: lwj123    时间: 2015-2-6 23:03
  1. Integer i = new Integer(127);
  2. 源代码:
  3. public static Integer valueOf(int i) {
  4.         if (i >= IntegerCache.low && i <= IntegerCache.high)//如果i>-128&&i<=127
  5.             return IntegerCache.cache[i + (-IntegerCache.low)];
  6.         return new Integer(i);//超过了127或者小于-128

  7.         /*
  8.         ntegerCache.low:-128
  9.         IntegerCache.high:127       
  10.        
  11.         //是一个数组,静态修饰
  12.         static final Integer cache[];
  13.        
  14.         //给这个数组赋值
  15.         int j = low;
  16.         for(int k = 0; k < cache.length; k++)
  17.             cache[k] = new Integer(j++);
  18.         //该数组在类加载时就已经对每一个值赋值了,范围是-128,127,因为cache是由static修饰所以在这个范围内都是同一个对象
  19.         //超过了127或者小于-128,返回new Integer(i);这是新的对象了,所以才有


  20. Integer i1 = 127;
  21. Integer i2 = 127;
  22. System.out.println(i1.equals(i2));//true
  23. System.out.println(i1==i2);//true
  24. 以上是对这两个结果的源码解释
  25.         */
  26. }
复制代码

作者: qiuyuhuaihua    时间: 2015-2-6 23:08
Java 中的参数传递 值传递?or 引用传递?
以前接触过C/C++,所以总感觉Java中的参数传递理解起来总感觉有点怪怪的,没有C家族语言来的方便,但是其实只要掌握好三个点就可以了:
1、基本数据类型,如int、boolean、double等在参数传递时都是值传递,也就是说,在外部函数修改传入的值对原变量是没影响的。
2、如果传递的是对象引用,如果Object、Person、Integer等等,那么在外部函数类对其的修改是能修改原对象的。
3、特殊情况,那就是String了,按理说它是引用类型,不是基本数据类型,但是它在参数传递时的的确确表现出来的是基本数据类型的特征。
好了,大家若不深究,记住这三条就可以了,至于更深层次的理解限于篇幅我也就不献丑了,传送门已经为你们准备好,自行加深理解吧:http://blog.sina.com.cn/s/blog_59ca2c2a0100qhjx.html
作者: 浮夸    时间: 2015-2-6 23:14
好复杂(⊙o⊙)…
作者: MacxChina    时间: 2015-2-6 23:21
创建UIPageViewController时指定了页面书脊位置位于屏幕的中间,
那么该控制器初始就需要显示2个页面,所以必须为该方法传入2个UIViewController作为初始的显示页面!
作者: @coffee    时间: 2015-2-6 23:32
                Collection li = new HashSet();
                ReflectPoint rp1 = new ReflectPoint(3,3);
                ReflectPoint rp2 = new ReflectPoint(5,5);
                ReflectPoint rp3 = new ReflectPoint(3,3);
               
                li.add(rp1);
                li.add(rp2);
                li.add(rp3);
                li.add(rp1);
               
                rp1.y = 8;
               
                li.remove(rp1);
               
                System.out.println(li.size());

HashSeyt集合中存在 内存泄露问题。

原因:更改元素的值时 元素相对应的哈希值也会改变,导致删除时找不到元素。
作者: 王占军    时间: 2015-2-6 23:33
好深奥,我还没有学到这里哦,加油吧!
作者: doomsday    时间: 2015-2-7 00:24
love$$-IT 发表于 2015-2-6 18:58
观察源代码:增强for,底层其实就是通过迭代器来实现的。
通过迭代器来实现hasNext(),next(),rmove()等方法 ...

哥们请问增强for的源码可以在哪里看
作者: kenfine    时间: 2015-2-7 07:34
doomsday 发表于 2015-2-7 00:24
哥们请问增强for的源码可以在哪里看

这个问题问的好!
作者: coolmiao13    时间: 2015-2-7 10:59
StringBuffer s1 = new StringBuffer("a");

StringBuffer s2 = new StringBuffer("a");

s1.equals(s2)//为什么是false

String s1 = new String("a");

String s2 = new String("a");

s1.equals(s2)//为什么是true

StringBuffer类中没有重新定义equals这个方法,因此这个方法就来自Object类,

而Object类中的equals方法是用来比较地址的,所以等于false.

String类中重新定义了equals这个方法,而且比较的是值,而不是地址。所以会是

true。
作者: janstk    时间: 2015-2-7 18:53
分享个小技巧,
if判断语句的时候可以把常量放在前面,防止出现==写成=的错误。
比如
int aa= 10;
if(10==aa)
{
  //to do
}
作者: 温晓慧    时间: 2015-2-7 21:22
自增自减不具有原子性,在并发操作时,不安全,需要同步!
作者: love$$-IT    时间: 2015-2-7 21:38
public class IntegerTest {
        public static void main(String[] args) {
                Integer a=121;  // a=new Integer(121);
                Integer b=121;  //b=new Integer(121);
                //同一个对象, 使用的都是内部的cache 维护的Integer 对象.
               //是同一个对象,地址值是相同的
                System.out.println(a==b);// true
               
                Integer c=129;
                Integer d=129;
                // 两个对象. 129 超出了cache的范围.  new 两次对象. 所有== 比较对象内存地址为false .
                System.out.println(c==d);// false
        }
作者: 许慎誉    时间: 2015-2-7 21:51
当我们使用多态,父类的引用指向了子类的对象,这实际上是将子类的引用向上自动转型为父类的引用类型;
向上转型:将子类的对象引用,可以自动转换为父类的引用;
向下转型:多态中,可以将父类的引用,强制转换为它所指向的那个子类的类型。
                    注意:要保证强制转换时,所转换的类型一定要是之前父类所指向那个类型;
                        class A
{
        void show(){
                System.out.println("A-->show()");
        }
}
class B extends A
{
        void fun(){
                System.out.println("B-->fun()");
        }
}
class C extends A
{
}
class Demo
{
        public static void main(String[] args)
        {
                A a = new B();//自动的、向上转型
                a.show();//访问的是父类的
        //        a.fun();//编译错误。不能访问子类自有的成员;

                //显示的向下转型,强制转换
                B b = (B)a;
                b.show();//OK
                b.fun();//OK
                A a1 = new B();
        //        C c = (C)a1;//运行时异常
作者: Aily    时间: 2015-2-7 22:46
关于代码String str = new String(“abc”);  
注意  是创建了"两个对象 "  一个是new String( ) 对象  存在于堆内存中,  另一个是"abc"保存在常量池中

注意  String  是一个特别的类   String的常量存在于常量池中  常量池在方法区中 ------------  图解  去看视频  老师讲的很清楚

注意          str.equals(“abc”);将返回true
                 (str =="abc")将返回:false   
   解释:   equals   比较的是真正的代表的  东西 而   ==  比较的是地址值

equals  的源代码
  public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String) anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                            return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

并且  String类在调用时  不用倒包   是一个  特殊的  引用类型类  

还有一点  输出语句System.out.println("++");你会发现输出的都是双引号引起来的东西哎
解释:  因为输出语句  默认重写了toString()  方法   而且  输出引用类型变量时  为地址值  
   但是   输出char数组时   是输出   数组的第一个元素   因为  char数组  直接执行原代码   不经过重写的toString语句


以上  是我的  部分总结   


作者: love$$-IT    时间: 2015-2-7 22:50
kenfine 发表于 2015-2-7 07:34
这个问题问的好!

好吧!我是听了去看的迭代器,但是这个增强for的内部实现确实是通过迭代器来实现的。
作者: Piaget    时间: 2015-2-7 22:52
对象初始化:
子类初始化必须访问父类
先加载成员变量,后加载成员函数
(但是通过super初始化父类内容时,子类的成员变量并未显示初始化;           
等super父类初始化完毕后才进行子类的成员变量显示初始化。)  

作者: 温晓慧    时间: 2015-2-7 23:14
Piaget 发表于 2015-2-7 22:52
对象初始化:
子类初始化必须访问父类
先加载成员变量,后加载成员函数

恩恩。今天还看到先加载静态的,后加载构造函数~~~
作者: 彭春晓    时间: 2015-2-8 12:01
对象new一个两个礼拜,基础打牢了,才能学好新东西。
作者: Aily    时间: 2015-2-8 13:24
彭春晓 发表于 2015-2-8 12:01
对象new一个两个礼拜,基础打牢了,才能学好新东西。

是的  我现在在双元的java基础班  深有体会   面向对象这一块很重要  直接影响你后面的学习   特别是 new  很多人都跪在了这里 包括我在内


所以   一定要搞清楚   不过  我今天恶补了一下   感觉清楚多了  那个  数组中刚出现new的时候  把内存图搞懂   然后  后面的存储和内在原理  你就明白的多  轻松很多   

作为过来人的建议:)
作者: Aily    时间: 2015-2-8 13:26
是的  我现在在双元的java基础班  深有体会   面向对象这一块很重要  直接影响你后面的学习   特别是 new  很多人都跪在了这里 包括我在内


所以   一定要搞清楚   不过  我今天恶补了一下   感觉清楚多了  那个  数组中刚出现new的时候  把内存图搞懂   然后  后面的存储和内在原理  你就明白的多  轻松很多   

作为过来人的建议:)
作者: Oo不弃    时间: 2015-2-8 14:13

Java中a++与++a的区别:
a++是先调用再自加,++a是先自加再调用,举例说明:
int a = 1;
int b = a++ + 1;
此时b是等于2的(a的值本来就等于1,1+1=2,a先调用完才进行自增)
int a = 1;
int b = ++a + 1;
此时b是等于3的(a先自增1,等于2,然后2+1=3)
再举一个例子:
int a = 1;
int b = a++ + 1;
int c = a+1;
此时b等于2,c等于3,(在int b = a++ + 1操作完成后,a已经执行了自增操作,所以在第二次调用时,a的值已经变化了)


作者: 彭春晓    时间: 2015-2-8 16:30
Aily 发表于 2015-2-8 13:24
是的  我现在在双元的java基础班  深有体会   面向对象这一块很重要  直接影响你后面的学习   特别是 new ...

谢谢,其实也有觉得,这个特别重要。

----别停下追逐梦想的脚步
作者: x1071765330    时间: 2015-2-8 21:37
赞!!!!
作者: 许慎誉    时间: 2015-2-8 22:39
昨天看到一个问字符串类型怎么转换成int型,今天再找没找到,就把总结的String和int相互转换的方法发在这吧!希望大家一起交流
一.int到String:
  1.使用0长度字符串进行字符串连接
    String str = "" + num;
  2.String.valueOf(int i);
二.String到int:
   1.Integer的构造方法;
    Integer a = new Integer(str2);
        int num1 = a.intValue();
   2.Integer的static valueOf(String s);
Integer b = Integer.valueOf(str2);
                int num2 = b.intValue();
  3.Integer的static parseInt(String s);
int num3 = Integer.parseInt(str2);
作者: 张_磊    时间: 2015-2-8 22:50
import java.util.ArrayList;

public class ListStudent {
        public static void main(String[] args) {
                // 创建集合对象
                List list = new ArrayList();
                // 创建元素对象
                Student s = new Student("赵默笙", 24);
                Student s1 = new Student("何以琛", 25);
                Student s2 = new Student("路远风", 23);
                Student s3 = new Student("林少梅", 24);
                // 存储元素
                list.add(s);
                list.add(s1);
                list.add(s2);
                list.add(s3);
                // 遍历集合
                ListIterator lt = list.listIterator();
                while (lt.hasNext()) {
                        Student s4 = (Student) lt.next();
                        System.out.println(s4.getName() + "***" + s4.getAge());
                }
                //反向遍历
                while(lt.hasPrevious()){
                        Student s5 = (Student) lt.previous();
                        System.out.println(s5.getName()+"***"+s5.getAge());
                }
        }
}

集合中的ListIteratoer中的小知识( 上面没有写出学生类,只写了个测试类。)
ListIterator迭代器中有反向迭代的方法
判断是否有前一个元素boolean hasPrevious()
返回前一个元素Object previous()
但是必须通过ListIterator迭代器正向遍历之后才能使用反向遍历。        个人感觉没什么用处。               

作者: 会飞d猪    时间: 2015-2-9 00:47
出现空指针异常的原因是null调用类方法。
作者: linuxpara910829    时间: 2015-2-9 03:33
刚学到反射,说说自己对反射的理解吧。
总的来说反射就是逆向操作。
先拿到类的字节码,然后通过字节码获取构造函数,字段,方法。然后再来操作这些构造函数,字段,方法。这种操作是反向的,跟我们写代码的时候思路是反着的,所以刚开始学反射的时候都觉得挺难,把思想转过来,倒着走会感觉好多,个人想法有不对的地方希望大神们指出来,多多学习
作者: 田得聖老师    时间: 2015-2-9 09:05
qiuyuhuaihua 发表于 2015-2-6 22:57
Java 中的参数传递 值传递?or 引用传递?

Java中都是引用传递的,只有地址值被传递了
作者: 书生灬流年    时间: 2015-2-9 10:58
try catch finally 语句中如果try中有return 而finally中也有的话,try中的是执行不到的。
作者: 梁小刀11    时间: 2015-2-10 00:03
水水更健康!~别蜂窝啊.
作者: wenyu    时间: 2015-2-10 10:03
邓士林 发表于 2015-2-6 11:05
还是说说==和equals,因为今天我才明白。
【==是比较对象的时候比较内存,equals底层也是用==实现】这句话 ...

我觉得这个问题只要理解了常量池的问题就不难理解了吧。栈和堆里的东西最终还是指向常量池的,只是堆里的东西是两次创建的不同String,在堆里的的地址不同,但都是指向常量池的同一个字符串常量
作者: orsoul    时间: 2015-2-16 00:50
  1. short a = 1;
  2. a = a + 1;//报错
  3. a += 1; // 通过
复制代码

a += 1之所以通过是因为使用复合赋值运算符时编译器已自动强转
作者: Ansel    时间: 2015-2-16 01:24
菜鸟一个,完全看不懂
作者: 艺多不压身丶    时间: 2015-2-16 22:47
  1. package pack;
  2. class Demo implements Runnable{
  3.         public void run(){
  4.                 for(int x=0; x<60; x++){
  5.                         System.out.println(Thread.currentThread().getName()+" :"+x);
  6.                         // Thread.yield();
  7.                 }
  8.         }
  9. }
  10. class joinDemo{
  11.         public static void main(String[] args)throws InterruptedException{
  12.                 Demo d=new Demo();
  13.                 Thread t1=new Thread(d);
  14.                 Thread t2=new Thread(d);
  15.                 t1.start();
  16.                 t1.join();
  17.                 t2.start();
  18.         }
  19. }
复制代码

join:当t2线程执行到了t1线程的join方法时,t2就会等待,等t1线程都执行完,t2才会执行。
join可以用来临时加入线程。
发小了个小现象。就是要插入的线程必须放在其他线程的上面并且后面要跟的是join。这样才能正确的打印完你要插入的线程。
不知道我说的对不对。不过挺有意思的。
作者: orsoul    时间: 2015-2-17 00:22
最近发现的JDK7的新功能:
  1. // 可以在数值字面值中使用下划线,如:
  2. int i = 1_000_000;
  3. double d = 9.000_001;
  4. // 以上都是合法的代码,编译器会自行忽略掉下划线
  5. //还有,Java终于支持字面值的二进制表示了:
  6. int bi = 0b101;// 我都想不通,这么简单实用的功能,C语言不支持,JAVA到了第7版才支持
复制代码

作者: orsoul    时间: 2015-2-21 21:40
  1. // private方法都隐式地被指定为final的,但是当你覆盖一个private方法时,却能顺利通过编译:
  2.     class Father {
  3.         void Method1() {}
  4.         final void Method2() {}
  5.         private void Method3() {} // 相当于 private final void method3() {}
  6.     }
  7.    
  8.     class Son extends Father {
  9.         void Method1() {} // 通过。正常覆盖
  10.         void Method2() {} // 报错。无法覆盖被final修饰的方法
  11.         void Method3() {} // 通过。
  12.         /*  其实,父类中的private方法对子类是不可见的,
  13.             子类中的Method3()并没有覆盖父类中的方法而是一个新的方法,
  14.             只不过恰好与父类中的private方法同名。
  15.         
  16.             之前我还不太理解为什么在覆盖时,子类方法的权限不能比父类方法的小,
  17.             理解上述例子之后才知道原因所在。
  18.         */
  19.     }
复制代码

作者: 大手牵小手    时间: 2015-3-3 14:23
  1. double x=10
  2. while(x!=9.00)
  3. {
  4. x-=0.01
  5. }
复制代码

死循环,浮点数比较,精确到具体的二进制位,各个二进制位相等才算相等,浮点数表示的是近似值,不能用于比较
作者: 大手牵小手    时间: 2015-3-3 14:26
  1. for(int x=10;x>1;;)
  2. int x=15
复制代码

正确
  1. for(int x=10;x>1;;)
  2. x=15
复制代码

错误,循环中的变量在括号外无效
作者: 佟金    时间: 2015-3-9 19:22
Integer m = 128                                        Integer m = 127;
Integer n = 128;                                        Integer n = 127;
m==n?false,两个对象                                m==n?true,指向了同一个
当数值在byte范围内时,对于新特性,如果该数值已经存在,则不会再开辟空间。
作者: adolph    时间: 2015-3-16 00:24
terator对集合类中的任何一个实现类,都可以返回一个Iterator对象。就和循环一样,好处是可以适用于任何一个类,而且比直接用index访问快一点。
作者: Shey    时间: 2015-3-16 10:48
我就来说说基本类型包装类的valueOf吧,下面用Integer为例:

  1.                 /*1*///true
  2.                 Integer i1 = Integer.valueOf(1);
  3.                 Integer i2 = Integer.valueOf(1);
  4.                 System.out.println(i1==i2);
  5.                
  6.                 /*2*///false
  7.                 i1 = new Integer(1);
  8.                 i2 = new Integer(1);
  9.                 System.out.println(i1==i2);
  10.                
  11.                 /*3*///false
  12.                 i1 = new Integer(1);
  13.                 i2 = Integer.valueOf(1);
  14.                 System.out.println(i1==i2);
  15.                
  16.                 //了解过自动拆箱和装箱的同学都知道 Integer i = 1 其实就等同于 Integer i = Integer.valueOf(1);所以只有这三种
复制代码
其实我是查阅了源码才有根本上的理解的,如下:
  1. public static Integer valueOf(int i) {
  2.         if (i >= IntegerCache.low && i <= IntegerCache.high)
  3.             return IntegerCache.cache[i + (-IntegerCache.low)];
  4.         return new Integer(i);
  5.     }
复制代码

上面是Integer类里面valueOf的源码,Interger类中有一个内部内为IntegerCache意思就是缓存嘛,我们先不说它源码,只看cache;
  1. private static class IntegerCache {
  2.         static final int low = -128;
  3.         static final int high;
  4.         static final Integer cache[];
  5.         ......
  6.     }
复制代码

代码的意思是显而易见的cache是Integer类型的数组,cache本身就是缓存的意思,所以valueOf就是在指定范围内返回cache缓存中的值,超出范围则new一个,若当1存在于缓存cache中,上文的3个结果也就明了了IntegerCache.low==-128我们都知道了,下面我去深究下IntegerCache.high到底有多大,源码附上:
  1. static {
  2.     // high value may be configured by property
  3.     int h = 127;-------------------------------------------------------------------1
  4.     String integerCacheHighPropValue =
  5.         sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
  6.     if (integerCacheHighPropValue != null) {
  7.         try {
  8.             int i = parseInt(integerCacheHighPropValue);
  9.             i = Math.max(i, 127);
  10.             // Maximum array size is Integer.MAX_VALUE
  11.             h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
  12.         } catch( NumberFormatException nfe) {
  13.             // If the property cannot be parsed into an int, ignore it.
  14.         }
  15.     }
  16.     high = h;-----------------------------------------------------------------------2

  17.     cache = new Integer[(high - low) + 1];
  18.     int j = low;
  19.     for(int k = 0; k < cache.length; k++)
  20.         cache[k] = new Integer(j++);

  21.     // range [-128, 127] must be interned (JLS7 5.1.7)
  22.     assert IntegerCache.high >= 127;
  23. }
复制代码

这是IntegerCache中的静态代码块,在类加载的时候执行一次,我们直接看---1和---2处,中间代码不管,整个结构就只是给high赋值,循环建立从low到high大小的cache缓存数组,很简单吧,下面再看看1---2中间部分,我用注释的方式写出:
  1. String integerCacheHighPropValue =
  2.     sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");//读取javaInteger缓存最大值配置,默认127
  3. if (integerCacheHighPropValue != null) {
  4.     try {
  5.         int i = parseInt(integerCacheHighPropValue);
  6.         i = Math.max(i, 127); //若自行配制的最大值小于127,就取127
  7.         // Maximum array size is Integer.MAX_VALUE
  8.         h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
  9.         //这是Integer前面定义的常量public static final int MAX_VALUE = 0x7fffffff;
  10.         //若自行配制的最大值上限还是有限制的最大为:Integer.MAX_VALUE - (-low) -1
  11.     } catch( NumberFormatException nfe) {
  12.         // If the property cannot be parsed into an int, ignore it.
  13.     }
  14. }
  15. assert IntegerCache.high >= 127; //断言函数,自行百度
复制代码
最后:-D可以设置java.lang.Integer.IntegerCache.high
谢阅





作者: bianzhiguo6    时间: 2015-3-16 11:06
感觉都好厉害,我这个新手0基础的怎搞,何时才能赶上
作者: 小十    时间: 2015-3-16 11:55
java规定私有的东西不能被外界访问,要真想访问也有一道后门那就是通过暴力反射强暴它一把!
就要调用setAccessable方法,将其改为true。
作者: みぎ    时间: 2015-3-16 12:13
逗号操作符;
  1. public class Test {
  2.        
  3.         public void method() {
  4.                 for(int i=0, j=i+2; i<10; i++, j=j*2) {
  5.                         System.out.println("i = " + i + " j = " + j);
  6.                 }
  7.         }
  8. }
复制代码

for循环中,“,”后面的语句会独立执行。
     
作者: 43453186@qq.com    时间: 2015-3-22 15:52
还没看到这里,==再说。
作者: 夜班心桥    时间: 2015-3-22 21:37
System.out.println(char[] chs)输出结果为字符数组中的所有字符,而不是数组的地址。通过源码,发现,其底层是:OutputStream中的write(int a),所以结果是所有字符。




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