`

四道Java基础题,转自csdn

阅读更多

原文来于:http://blog.csdn.net/soul_code/article/details/50369947

 

一、==符的使用

首先看一段比较有意思的代码

Integer a = 1000,b=1000;
Integer c = 100,d=100;   
public void mRun(final String name){
    new Runnable() {    
        public void run() {
           System.out.println(name);
        }
    };
}
System.out.println(a==b);
System.out.println(c==d);

     如果这道题你能得出正确答案,并能了解其中的原理的话。说明你基础还可以。如果你的答案 是 true 和true的话,你的基础就有所欠缺了。

首先公布下答案, 运行代码,我们会得到 false  true。我们知道==比较的是两个对象的引用,这里的abcd都是新建出来的对象,按理说都应该输入false才对。这就是这道题的有趣之处,无论是面试题还是论坛讨论区,这道题的出场率都很高。原理其实很简单,我们去看下Integer.java这个类就了然了。

  public static Integer valueOf(int i) {
        return  i >= 128 || i < -128 ? new Integer(i) : SMALL_VALUES[i + 128];
    }

    /**
     * A cache of instances used by {@link Integer#valueOf(int)} and auto-boxing
     */
    private static final Integer[] SMALL_VALUES = new Integer[256];

    static {
        for (int i = -128; i < 128; i++) {
            SMALL_VALUES[i + 128] = new Integer(i);
        }
    }

  当我们声明一个Integer c = 100;的时候。此时会进行自动装箱操作,简单点说,也就是把基本数据类型转换成Integer对象,而转换成Integer对象正是调用的valueOf方法,可以看到,Integer中把-128-127 缓存了下来。官方解释是小的数字使用的频率比较高,所以为了优化性能,把这之间的数缓存了下来。这就是为什么这道题的答案回事false和ture了。当声明的Integer对象的值在-128-127之间的时候,引用的是同一个对象,所以结果是true。

二、String

接着看代码

                String s1 = "abc";
		String s2 = "abc";
		String s3 = new String("abc");
		System.out.println(s1 == s2);
		System.out.println(s1 == s3);

   大家又来猜一猜这道题的答案是什么?

       按照==的语法来看, 首先s1、s2、s3是三个不同的对象,常理来说,输出都会是false。然而程序的运行结果确实true、false。第二个输出false可以理解,第一个输出true就又让人费解了。我们知道一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,而堆内存中则存放new 出来的对象和数组。然而除此之外还有一块区域叫做常量池。像我们通常想String s1 = "abc"; 这样申明的字符串对象,其值就是存储在常量池中。当我们创建String s1 = "abc"这样一个对象之后,"abc"就存储到了常量池(也可叫做字符串池)中,当我们创建引用String s2  = "abc" 的时候,Java底层会优先在常量池中查找是否存在"abc",如果存在则让s2指向这个值,不会重新创建,如果常量池中没有则创建并添加的池中。这就是为什么答案是true 和false的原因。

三、final关键字

还是来看一段代码

	public void mRun(final String name){
		new Runnable() {
			
			public void run() {
                            try {
                              Thread.sleep(1000);
                           } catch (InterruptedException e) {
                             // TODO Auto-generated catch block
                            e.printStackTrace();
                           }  
                           System.out.println(name);
			}
		}.start();
	}
	

   这种代码相信大家写过很多,当内部类访问局部变量的时候,需要在局部变量前加final修饰符,不然编译器就会报错。通常我们也是这么干的。好的,第二个问题来了,为什么要加final修饰符?相信大多数小伙伴都没有思考过这个问题,但凡使用的时候,直接加上就得了,从来没去深究过其中的原理。这对于一个优秀的程序员来说是不可取,我们不仅要知其然还要知其所以然。

      现在我们来分析一下,为什么要加final关键字。首先内部类的生命周期是成员级别的,而局部变量的生命周期实在方法体之类。也就是说会出现这样一种情况,当mRun方法执行,new 的线程运行,新线程里面会睡一秒。主线程会继续执行,mRun执行完毕,name属性生命周期结束。1秒之后,Syetem.out.printh(name)执行。然而此时name已经寿终正寝,不在内存中了。Java就是为了杜绝这种错误,严格要求内部类中方位局部变量,必须使用final关键字修饰。局部变量被final修饰之后,此时会在内存中保有一份局部变得的复制品,当内部类访问的时候其实访问的是这个复制品。这就好像是把局部变量的生命周期变长了。说到底还是Java工程师提前把这个坑给我们填了,不然不知道又会有多少小伙伴会为了内部类局部变量而发愁了。

 

四、Integer与int那些事

看下面代码

	        Integer a = new Integer(1000);
		int b = 1000;
		Integer c = new Integer(10);
		Integer d = new Integer(10);
		System.out.println(a == b);
		System.out.println(c == d);

 这道题是继第一题的后续,如果这道题你能很快速的得出答案,那么恭喜你,==比较符你就算掌握的比较透彻了。

------------------------------------------------------分割线-----------------------------------------------------------------------

正确答案: true  、false 

看到这个答案很多小伙伴又会不解,先来说下第二个,按第一题来说Integer不是把-128-127缓存起来了吗?这不是应该是true嘛,但是你仔细看,这里的Integer是我们自己new出来的,并不是用的缓存,所以结果是false。 现在来看第一个为啥又是true了呢? 首先这里的值为1000,肯定和我们所知的Integer缓存没有关系。既然和缓存没有关系,a是新new出来的对象,按理说输入应该是false才对。但是注意b这里是int类型。当int和Integer进行==比较的时候,Java会把Integer进行自动拆箱,也就是把Integer转成int类型,所以这里进行比较的是int类型的值,所以结果即为true。

分享到:
评论

相关推荐

    2017java面试题

    "2017java面试题"这个压缩包文件提供了丰富的资源,帮助Java开发者准备面试,深化对Java开发的理解。 文档"Java面试宝典2017.doc"可能包含了以下核心Java知识点: 1. **基础语法**:这包括变量、数据类型、运算符...

    Java基础面试题

    java常见基础面试题

    java基础编程题

    java基础题,对初学者有很大的帮助。初学者可以根据自己学到的知识融合习题

    java笔试题库.pdf

    4. **提供Java存取数据库能力的包是?** - 答案:A(java.sql) - **解析**:`java.sql`包包含了用于处理SQL数据库的所有必要类和接口,例如`Connection`、`Statement`、`ResultSet`等。这些类和接口使得Java应用...

    java基础笔试题

    ### Java基础笔试题知识点解析 #### 第一组知识点详解 **1. 合法变量名规则** - **知识点概述:** 变量名是程序中标识变量的重要方式之一,Java对变量名有一定的规范要求。 - **详细解释:** - **A. 2variable:*...

    java基础面试题.pdf

    ### Java基础面试题知识点解析 #### 一、面向对象的特征 **面向对象编程(OOP)** 是Java的核心特性之一,其主要特征包括抽象、继承、封装和多态性。 1. **抽象**: 抽象是一种从众多事物中抽取出共同的、本质性的...

    java基础练习题

    ### Java基础知识点解析 #### 1. 整数排序算法 **题目描述**: 编写程序实现对给定的4个整数从大到小的顺序排列。 **知识点**: 这个题目涉及到基本的排序算法,如冒泡排序、选择排序等。在Java中可以通过循环和...

    100家大公司java笔试题汇总.docx

    本文档总结了Java编程语言的常见笔试题,涵盖了Java基础知识、面向对象编程、异常处理、Servlet、JDBC、J2EE等方面的知识点。 一、Java基础知识 1. Java中的abstract关键字可以修饰字段、方法和类,但抽象方法的...

    Java基础面试题整理(附答案)

    ### Java基础面试题知识点解析 #### 一、面向对象的特征 面向对象编程(OOP)是Java编程的核心概念之一,其主要特征包括: - **封装**:将对象的状态信息(属性)隐藏在对象内部,仅对外提供有限的操作接口。封装提高...

    JAVA基础测试题(含答案)

    这份"JAVA基础测试题(含答案)"的压缩包显然旨在帮助学习者检验和巩固他们的Java基础知识。让我们一起探讨这些测试题可能涵盖的知识点,以及这些知识点在实际编程中的重要性。 1. **Java语法基础**:测试题可能会...

    JAVA编程题全集(100题及答案)——直接打印

    1. JAVA 基础知识:资源中提到了 JAVA 程序设计总复习题,包括了基础的 JAVA 程序设计知识,如使用 `System.out.print` 输出字符串、使用 `if-else` 语句判断条件等。 2. JAVA 语句和结构:资源中提供了多种 JAVA ...

    Java基础练习代码

    Java基础是学习编程语言的重要阶段,对于初学者来说,掌握好这一阶段的知识是成为熟练Java开发者的基石。本文将深入探讨Java基础练习代码中的关键概念,帮助初学者巩固基础,提高编程技能。 首先,Java是一种面向...

    java面试题

    它是程序员进行 Java 开发的基础。 - **JRE (Java Runtime Environment)**:是 Java 运行时环境,包含了 JVM 以及必要的 Java 类库,使得 Java 程序可以在没有 JDK 的环境下运行。 - **JVM (Java Virtual Machine)**...

    50道java编程基础练习题及答案

    50道java编程基础练习题及答案http://u.download.csdn.net/images/btn_submit.png

    JAVA基础面试题(经典).doc

    【JAVA基础面试题详解】 1. **JDK与JRE的区别** JDK是Java Development Kit的缩写,它是Java开发工具包,包含了编译器、调试器和其他开发工具,用于编写、编译和测试Java应用程序。JRE是Java Runtime Environment...

    农行Java笔试题

    总的来说,"农行Java笔试题"将全面考察考生的Java基础知识和实际应用能力,需要考生对Java的各个方面都有深入理解和实践经验。只有扎实的基础和灵活的思维,才能在这样的考试中取得优异的成绩。

    JAVA 蓝桥杯试题

    【JAVA 蓝桥杯试题】是一套针对初学者的Java编程竞赛题目,旨在帮助学习者提高编程技能和解决问题的能力。试题分为“代码填空”和“程序设计”两大类,总分100分。代码填空部分要求考生理解已有代码逻辑,补充缺失...

Global site tag (gtag.js) - Google Analytics