`

java笔试题的整理和解答扩展(String专题)

    博客分类:
  • J2SE
阅读更多

很多公司的笔试题都是比较基础和原理性的,发现工作之后很少去看,要完整的解答出来还真不容易了,趁着这段时间去找一些笔试题来看看,也好补补基础原理的咚咚。

 

1.String str=new String("abc") 在内存中是怎么分配的?
2.String str1="abc" 和 String str1=new String("abc"); 这两个的区别是什么?

 

public class J0 {
public static void main(String[] args) {
String str1 = new String("strOne");
String str2 = new String("strOne");
String str3 = "strTwo";
String str4 = "strTwo";

System.out.println(str1 == str2);
System.out.println(str3 == str4);

}
}
估计答案是什么?
是不是false,false ?
因为 String 类不能直接 "==" 号比较!new 出来的两个String对象不在同一内存。
应该用 "equals()"。
------------------------------------
可是答案是:false,true;
------------------------------------
怎么理解呢?
问题有:
1)String str = new String("string");
  与 String str = "string";
  是否一致?有没有区别?
2)toString() 会不会调用 String()的构造函数呢?

----------------------------------------------
我的理解:
1)以前我认为一致,可是看上面的程序很明显不一样的。
2)看到toString()方法,我会想到调用了String() 的构造函数。
  可是:String str3 = "strTwo";
        String str4 = "strTwo";
  为什么构造出来是同一个String 对象呢?("strTwo"=>new StringBuffer

("strTwo").toString())


String str = new String("string");
 与 String str = "string";

声明:以下解释是保证正确的,我会从内存空间上来解释,比较清楚。

区别是,new String是在堆空间上分配一个空间,将指针指向这个空间,每一个new都是新的空间

,==判断当然是不等。

而String str = "ssss",说一下,在每种语言中对于字符串都有特殊的处理。
Java有一个专门的字符串池来保存可以重用的字符串。对于相同的字面值(也就是"双引号里面你

看到东西")相同,多少个变量他们都指向相同的空间,==判断当然相等。

所以最正确的判断字符串内容相等的方法,就是用equals方法。String类这个immuable的类已经覆

盖了这个从Object类继承的eqauls方法,达到了对于内容相等的判断。

【转载】关于Java String对象创建问题解惑

 

关于Java String对象创建问题解惑

先看看下面的代码

    public String makinStrings()
    {
           String s = "Fred";
            s = s + "47";
            s = s.substring(2, 5);
            s = s.toUpperCase();
            return s.toString();
    }

 

问:调用makinStrings方法会创建几个String对象呢。  答案:3个

 

    上面的方法有五条语句:现在让我们来一条一条分析一下。

String s = "Fred";   结论:创建了一个String对象

这条语句相当于String s = new String("Fred");
因此,毫无疑问,第一条语句创建了一个String对象,我想没有有疑问吧?

s = s + "47";   结论:未创建String对象

这条语句也许很多人认为是创建了String对象,我一开始也是这么认为的。但是为了验证我的想法。决定
用点法术恢复这条语句的本来面目。(有很多时候,编译器总是在里面搞一些小动作,javac.exe也不例外)

现在找到这个程序所生成的.class文件(假设是Test.class),找一个反编译工具,我推荐JAD,可以http://www.softpedia.com/progDownload/JAD-Download-85911.html下载下载后,有一个jad.exe,将其路径放到环境变量path中(只限windows)。并在.class文件的当前路径执行如下的命令:

jad Test

然后大喊一声“还我本来面目” 

会在当前目录下生成一个Test.jad文件,打开它,文件内容如下:

... ...
    public String makinStrings()
     {
        String s = "Fred";
        s = (new StringBuilder(String.valueOf(s))).append("47").toString();
        s = s.substring(2, 5);
        s = s.toUpperCase();
        return s.toString();
   }
... ...

哈哈,其他的语句都没变,只有第二条变长了,虽然多了个new,但是建立的是StringBuilder对象。原来
这是java编译器的优化处理。原则是能不建String对象就不建String对象。而是用StringBuilder对象
加这些字符串连接起来,相当于一个字符串队列。这种方式尤其被使用在循环中,大家可以看看下面的代码:
      String s = "";
      for(int i=0; i < 10000000; i++)
            s += "aa";
没有哪位老大认为这是建立了10000000个String对象吧。但不幸的是,上面的代码虽然没有建立10000000个String对象但却建立了10000000个StringBuilder对象,那是为什么呢,自已用jad工具分析一下吧。正确的写法应该是:

        StringBuilder sb = new StringBuilder("");
        for(int i=0; i < 10000000; i++)
            sb.append(String.valueOf(i));

         s = s.substring(2, 5);     结论:创建了一个String对象也许有很多人一开始就认为这条语句是创建了一个String对象,那么恭喜你,这条语句确实创建了一个String对象实际上就是substring方法创建了一个String对象。这也没什么复杂的,自已下一个JDK源代码,看看substring是如何实现的就可以知道了。我先说一下吧。先不用管substring是如何实现的,反正在substring方法返回时使用了一个new显式地建立了一个String对象不信自己看看源码。
        s = s.toUpperCase();   结论:创建了一个String对象

toUpperCase()和substring方法类似,在返回时也是使用了new建立了一个String对象。

return s.toString();   结论:未创建String对象

toString方法返回的就是this,因此,它的返回值就是s。

这道题还算比较简单,再给大家出一个更复杂一点的,也是关于String对象的创建的(只是改了一个原题)。

    public String makinStrings()
   {
       String s = "Fred";
        s = s + "Iloveyou.".substring(1).toLowerCase();
        s = s.substring(0);
        s = s.substring(0,1).toUpperCase();
        return s.toString();
    }

先公布答案吧,上述代码也创建了3个String对象,哈哈!

 

为什么呢?

 

要想知道为什么,先得弄清楚substring、toLowerCase和toUpperCase什么时候创建String对象,什么时候不创建对象。

substring方法在截取的子字符串长度等于原字符串时,直接返回原字符串。并不创建新的String对象。

toLowerCase方法在字符串中更本没有需要转换的大写字母时直接返回原字符串,如"abcd".toLowerCase()直接返回abcd,并不创建新的String对象

toUpperCase方法和toLowerCase类似。"ABCD".toUpperCase()直接返回ABCD。

 

知道了这个,上面的代码就非常清楚了。

 

    public String makinStrings()
    {
        String s = "Fred";     //创建一个String对象
        s = s + "Iloveyou.".substring(1).toLowerCase();  //substring(1)创建一个String对象,由于toLowerCase()转换的字符串是"loveyou.",没有大写字母,因此,它不创建新的String对象
        s = s.substring(0);   // 由于substring(0)截获的是s本身,因此,这条语句不创建新的String对象
        s = s.substring(0,1).toUpperCase();  //substring(0,1)创建了一个String对象, 但由于substring(0,1)的结果是"F",为一个大写字母,因此,toUpperCase直接返回"F"本身。
     return s.toString();
    }

讲的好像有点道理,但是我用jad试了,反编译后的文件并不是他说的那样?那位试出来告诉一声!!!

 

 

 

【转】

初学 Java 有段时间了,感觉似乎开始入了门,有了点儿感觉但是发现很多困惑和疑问而且均来自于最基础的知识折腾了一阵子又查了查书,终于对 String 这个特殊的对象有了点感悟大家先来看看一段奇怪的程序:
public class TestString {    
  public static void main(String[] args) {        
  String s1 = "Monday";        
  String s2 = "Monday";    
  }
}
这个程序真是简单啊!可是有什么问题呢?
1. 来自 String 的忧虑上面这段程序中,到底有几个对象呢?
可能很多人脱口而出:两个,s1 和 s2为什么?String 是 final 类,它的值不可变。看起来似乎很有道理,那么来检测一下吧,稍微改动一下程序就可以看到结果了:
public class TestString {    
public static void main(String[] args) {    
    String s1 = "Monday";    
    String s2 = "Monday";  
     if (s1 == s2)      
       System.out.println("s1 == s2");      
    else      
      System.out.println("s1 != s2");
    }
}
呵呵,很多人都会说已经不止两个对象了编译并运行程序,输出:s1 == s2啊!
为什么 s1 == s2 ?
== 分明是在说:s1 与 s2 引用同一个 String 对象 -- "Monday"!
2. 千变万化的 String再稍微改动一下程序,会有更奇怪的发现:
public class TestString {    
  public static void main(String[] args) {        
    String s1 = "Monday";        
    String s2 = new String("Monday");        
    if (s1 == s2)            
       System.out.println("s1 == s2");        
    else            
       System.out.println("s1 != s2");        
    if (s1.equals(s2))            
        System.out.println("s1 equals s2");      
    else            
        System.out.println("s1 not equals s2");    
  }
}
我们将 s2 用 new 操作符创建程序输出:
s1 != s2s1 equals s2
嗯,很明显嘛s1 s2分别引用了两个"Monday"String对象
可是为什么两段程序不一样呢?
3. 在 String 的游泳池中游泳哈哈,翻了翻书终于找到了答案:
原来,程序在运行的时候会创建一个字符串缓冲池当使用 s2 = "Monday" 这样的表达是创建字符串的时候,程序首先会在这个String缓冲池中寻找相同值的对象,在第一个程序中,s1先被放到了池中,所以在s2被创建的时候,程序找到了具有相同值的 s1将 s2 引用 s1 所引用的对象"Monday"第二段程序中,使用了 new 操作符,他明白的告诉程序:“我要一个新的!不要旧的!”与是一个新的"Monday"Sting对象被创建在内存中。他们的值相同,但是位置不同,一个在池中游泳一个在岸边休息。哎呀,真是资源浪费,明明是一样的非要分开做什么呢?
4. 继续潜水再次更改程序:
public class TestString {
    public static void main(String[] args) {
        String s1 = "Monday";
        String s2 = new String("Monday");
        s2 = s2.intern();
        if (s1 == s2)
            System.out.println("s1 == s2");
        else
            System.out.println("s1 != s2");
        if (s1.equals(s2))
            System.out.println("s1 equals s2");
        else
            System.out.println("s1 not equals s2");
    }
}
这次加入:s2 = s2.intern();
哇!程序输出:s1 == s2s1 equals s2原来,程序新建了 s2 之后,又用intern()把他打翻在了池里哈哈,这次 s2 和 s1 有引用了同样的对象了我们成功的减少了内存的占用5. == 与 equals() 的争斗String 是个对象,要对比两个不同的String对象的值是否相同明显的要用到 equals() 这个方法可是如果程序里面有那么多的String对象,有那么多次的要用到 equals ,哦,天哪,真慢啊更好的办法:把所有的String都intern()到缓冲池去吧最好在用到new的时候就进行这个操作String s2 = new String("Monday").intern();嗯,大家都在水池里泡着了吗?哈哈现在我可以无所顾忌的用 == 来比较 String 对象的值了真是爽啊,又快又方便!


String 啊 String ,让我说你什么好呢?你为我们 Java 程序员带来所有的困扰还不够吗?
看看 String 这一次又怎么闹事儿吧
1. 回顾一下坏脾气的 String 老弟
例程1:class Str {
    public static void main(String[] args) {
        String s = "Hi!";
        String t = "Hi!";
        if (s == t)
            System.out.println("equals");
        else
             System.out.println("not equals");
    }
}
程序输出什么呢?
如果看客们看过我的《来自 String 的困惑》之一相信你很快会做出正确的判断:程序输出:equals
2. 哦,天哪,它又在搅混水了
例程2:class Str {
    public static void main(String[] args) {
        String s = "HELLO";
        String t = s.toUpperCase();
        if (s == t)
            System.out.println("equals");
        else
            System.out.println("not equals");
    }
}
那么这个程序有输出什么呢?
慎重!再慎重!不要被 String 这个迷乱的家伙所迷惑!
它输出:equalsWHY!!!
把程序简单的更改一下:
class Str2 {
    public static void main(String[] args) {
        String s = "Hello";
        String t = s.toUpperCase();
        if (s == t)
            System.out.println("equals");
        else
            System.out.println("not equals");
    }
}
你可能会说:不是一样吗?不!千真万确的,不一样!这一次输出:
not equalsOh MyGOD!!!
谁来教训一下这个 String 啊!
3. 你了解你的马吗?
“要驯服脱缰的野马,就要了解它的秉性”牛仔们说道。
你了解 String 吗?解读 String 的 API ,可以看到:toUpperCase() 和 toLowerCase() 方法返回一个新的String对象,它将原字符串表示字符串的大写或小写形势;但是要注意:如果原字符串本身就是大写形式或小写形式,那么返回原始对象。这就是为什么第二个程序中 s 和 t 纠缠不清的缘故对待这个淘气的、屡教不改的 String ,似乎没有更好的办法了让我们解剖它,看看它到底有什么结构吧:
(1) charAt(int n) 返回字符串内n位置的字符,第一个字符位置为0,最后一个字符的位置为length()-1,访问错误的位置会扔出一块大砖头:StringIndexOutOfBoundsException 真够大的
(2) concat(String str) 在原对象之后连接一个 str ,但是返回一个新的 String 对象
(3) EqualsIgnoreCase(String str) 忽略大小写的 equals 方法这个方法的实质是首先调用静态字符方法toUpperCase() 或者 toLowerCase() 将对比的两个字符转换,然后进行 == 运算
(4) trim() 返回一个新的对象,它将原对象的开头和结尾的空白字符切掉同样的,如果结果与原对象没有差别,则返回原对象
(5) toString() String 类也有 toString() 方法吗?真是一个有趣的问题,可是如果没有它,你的 String 对象说不定真的不能用在System.out.println() 里面啊小心,它返回对象自己String 类还有很多其他方法,掌握他们会带来很多方便也会有很多困惑,所以坚持原则,是最关键的
4. 我想买一匹更好的马来购买更驯服温和的 String 的小弟 StringBuffer 吧
这时候会有人反对:
它很好用,它效率很高,它怎么能够是小弟呢?
很简单,它的交互功能要比 String 少,如果你要编辑字符串它并不方便,你会对它失望但这不意味着它不强大public final class String implements Serializable, Comparable, CharSequencepublic final class StringBuffer implements Serializable, CharSequence很明显的,小弟少了一些东东,不过这不会干扰它的前途StringBuffer 不是由 String 继承来的不过要注意兄弟它也是 final 啊,本是同根生看看他的方法吧,这么多稳定可靠的方法,用起来比顽皮的 String 要有效率的多? Java 为需要改变的字符串对象提供了独立的 StringBuffer 类它的实例不可变(final),之所以要把他们分开是因为,字符串的修改要求系统的开销量增大,占用更多的空间也更复杂,相信当有10000人挤在一个狭小的游泳池里游泳而岸边又有10000人等待进入游泳池而焦急上火又有10000人在旁边看热闹的时候,你这个 String 游泳池的管理员也会焦头烂额在你无需改变字符串的情况下,简单的 String 类就足够你使唤的了,而当要频繁的更改字符串的内容的时候,就要借助于宰相肚里能撑船的StringBuffer 了
5. 宰相肚里能撑船
(1) length() 与 capacity()String 中的 length() 返回字符串的长度兄弟 StringBuffer 也是如此,他们都由对象包含的字符长度决定capacity()呢?
public class TestCapacity {
    public static void main(String[] args){
     StringBuffer buf = new StringBuffer("it was the age of wisdom,");
       System.out.println("buf = " + buf);
        System.out.println("buf.length() = " + buf.length());
        System.out.println("buf.capacity() = " + buf.capacity());
        String str = buf.toString();
        System.out.println("str = " + str);
        System.out.println("str.length() = " + str.length());
        buf.append(" " + str.substring(0,18)).append("foolishness,");
        System.out.println("buf = " + buf);
        System.out.println("buf.length() = " + buf.length());
        System.out.println("buf.capacity() = " + buf.capacity());
       System.out.println("str = " + str);
   }
}
程序输出:
buf = it was the age of wisdom.buf.length() = 25
buf.capacity() = 41
str = it was the age of wisdomstr.length() = 25
buf = it was the age of wisdom, it was the age of foolishness,
buf.length() = 56
buf.capacity() = 84
str = it was the age of wisdom,
可以看到,在内容更改之后,capacity也随之改变了长度随着向字符串添加字符而增加而容量只是在新的长度超过了现在的容量之后才增加StringBuffer 的容量在操作系统需要的时候是自动改变的程序员们对capacity所能够做的仅仅是可以在初始化 StringBuffer对象的时候。

分享到:
评论
1 楼 opalescent_ 2012-09-17  
学习了。。

相关推荐

    java笔试题大汇总

    Java笔试题涵盖了许多核心概念,这里我们逐一详细讨论: 1. 面向对象的特征: - 抽象:抽象是将复杂的问题简化,关注关键特性,忽略无关细节。在Java中,抽象主要体现在抽象类和接口。 - 继承:继承允许创建新类...

    JAVA笔试题,面试题JAVA笔试题,面试题

    【JAVA笔试题与面试题详解】 1. **Java基础知识** - Java的基本数据类型包括整型(byte, short, int, long)、浮点型(float, double)、字符型(char)和布尔型(boolean)。String不是基本数据类型,而是类,它...

    Java笔试题大集合及答案.doc

    Java编程语言中包含众多知识点,这里我们主要讨论的是与Java基础、内存管理和垃圾回收相关的概念。 首先,垃圾回收(Garbage Collection, GC)是Java内存管理的重要机制。它的工作原理是跟踪并管理堆内存中的对象,...

    java面试笔试题整理.doc

    在Java面试和笔试中,掌握核心的Java知识是至关重要的。以下是一些关键点的详细解释: 1. **面向对象的特征**:面向对象编程(OOP)的四大特征是抽象、继承、封装和多态性。 - **抽象**:抽象是忽略不相关细节,...

    java笔试题很有用的

    ### Java笔试题知识点详解 #### 一、面向对象的基本特征 面向对象编程(OOP)是现代软件工程的基础之一,其核心思想是通过“对象”来模拟现实世界中的实体及其交互方式。面向对象的四大基本特征分别是:抽象、继承、...

    Java笔试题与详细讲解

    ### Java笔试题与详细讲解知识点总结 #### 一、面向对象的基本特征 1. **抽象**:抽象是指在设计类时,关注类的核心功能而忽略不必要的细节。它可以帮助开发者更好地聚焦于类的主要职责,减少不必要的复杂性。抽象...

    Java笔试题Java笔试题

    在标题和描述中反复提到的“Java笔试题”暗示了这份文档是针对Java编程语言的考试准备资料。这可能包含了常见的面试问题、编程挑战或理论知识测试,旨在帮助求职者或学习者提高他们对Java的理解和应用能力。 ### 2....

    超级经典java笔试题总结(1)

    以下是对一些经典Java笔试题的解析: 1. `final`关键字的使用: 当声明一个实例变量(成员变量)为`final`时,必须在构造器中给它赋值。题目中的`final int i`没有初始值,因此会报错。正确做法是在声明时或构造器...

    java笔试题 75道

    - **多态性**:多态性允许不同的类对象对相同的消息作出响应,提高了代码的灵活性和可扩展性。 ### 15. String 类型的理解 `String` 是 Java 中的对象类型,用于表示不可变的字符序列,不是基本数据类型。基本数据...

    常见Java笔试面试题

    【Java笔试面试题详解】 1. **面向对象的特征** - **抽象**:抽象是对象和类概念的基础,它允许我们将关注点集中在问题的关键部分,忽略不相关的细节。抽象分为过程抽象(方法)和数据抽象(类)。 - **继承**:...

    初级java程序员面试题笔试题.pdf,这是一份不错的文件

    Java 程序员面试题笔试题笔记 标题解释 初级 Java 程序员面试题笔试题是面向初级 Java 程序员的笔试题,这份文件提供了多个问题,涵盖了 Java 语言的基础知识点,包括面向对象编程、数据类型、运算符、控制流程、...

    java笔试题大汇总(史上最全)

    【Java笔试题大汇总】是针对多家大型IT公司笔试题目的综合整理,涵盖了许多重要的Java编程知识点。以下是对这些知识点的详细解释: 1. **面向对象的特征**: - **抽象**:抽象是将复杂问题简化的过程,忽略不相关...

    JAVA笔试题大全

    下面将详细解释【标题】"JAVA笔试题大全"中涉及的一些核心知识点。 1. **面向对象的特征** - **抽象**:抽象是将复杂的问题简化,关注主要部分,忽略不重要的细节。在Java中,抽象主要体现在抽象类和接口,它们...

    支付宝Java工程师笔试题

    ### 支付宝Java工程师笔试题解析 #### 智力部分 1. **烧绳问题** **题目:** 烧一根不均匀的绳子需要一个小时,如何利用这根绳子判断出半小时的时间? **解答:** 将绳子的两端同时点燃,由于燃烧不均匀,无法...

    java基础笔试题

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

    华为Java笔试题附答案

    在华为的Java笔试中,考察的知识点广泛且深入,涵盖了Java语言的基础、进阶特性、数据结构、算法、多线程、网络编程、设计模式等多个方面。以下将根据标题和描述,结合Java的相关知识,详细解析可能涉及的考点。 1....

    2022美的集团Java开发岗位笔试题目.docx

    它采用了MVC(Model-View-Controller)设计模式,将业务逻辑、数据和界面分离,提高了代码的可维护性和可扩展性。Controller作为控制层接收用户的请求,并调用Model处理相应的业务逻辑,处理完毕后将结果返回给View...

    java笔试题大集合及答案(另附各大公司笔试题)

    12. **算法与数据结构**:虽然Java笔试题可能不会直接要求实现复杂的算法,但对基础算法的理解(如排序、查找、图论等)和数据结构(如栈、队列、链表、树等)的掌握,可以提高解题效率。 以上这些知识点都是Java...

    java各名企笔试题汇总

    Servlet具有更好的性能和可扩展性,支持多线程,而CGI每次请求都需要启动一个新的进程,效率较低。 5. **ArrayList vs Vector vs LinkedList**:`ArrayList`和`Vector`都是基于数组实现的列表,但`Vector`是线程...

    常见的java面试笔试题大汇总

    在Java编程领域,面试和笔试题常常涉及到核心概念和技术,以评估候选人的理解和技能。以下是一些关键知识点的详细说明: 1. **抽象**:在Java中,抽象是设计类时忽略不重要的细节,专注于主要功能的过程。抽象类...

Global site tag (gtag.js) - Google Analytics