JAVA开发面试题&String篇&第一部分
JAVA开发面试题&String篇&第一部分
- 1.下面程序的运行结果是()(选择一项)
- 2.Java语言中,String类中的indexOf()方法返回值的类型是()
- 3.给定以下代码,程序的运行结果是 ()
- 4.执行下列代码后,哪个结论是正确的()(选择两项)
- 5.实现String类的replaceAll方法
- 6.在“=”后填写适当的内容:
- 7.是否可以继承String类?
- 8.String类为什么是final的
- 9.给定两个字符串s和t, 写一个函数来决定是否t是s的重组词。你可以假设字符串只包含小写字母。
- 10.String s=new String(“abc”);创建了几个String对象?
- 11.输出结果?
- 12.下面哪个是正确的()
- 13.字符串如何转换为int类型
- 14.写一个方法,实现字符串的反转,如:输入abc,输出cba
- 15.编写java,将“I follow Bill Gate.Tom Gate.John Gate”中的“Gate”全部替换为“Gates”
- 16.String 是最基本的数据类型吗?
- 17.String 和StringBuilder、StringBuffer 的区别?
- 18.String s="Hello";s=s+"world!";执行后,是否是对前面s指向空间内容的修改?
- 19.String s = new String("xyz");创建几个String Object?
- 20.下面这条语句一共创建了多少个对象:String s="a"+"b"+"c"+"d";
面试知识点内容较多,本文为 String篇 的 第一部分,string篇预计 1篇.
本文应公众号用户需求发布,本篇为 String篇 ,过于基础,免费,请需要者自取。
点击跳转上一篇章, 基础篇 第一部分: https://blog.csdn.net/zsk1996888/article/details/109600251.
点击跳转下一篇,集合篇第一部分: link.
1.下面程序的运行结果是()(选择一项)
String str1="hello";
String str2=new String("hello");
System.out.println(str1==str2);
选项 | 内容 |
---|---|
A | true |
B | false |
C | hello |
D | he |
答案:B
分析:str1没有使用new关键字,在堆中没有开辟空间,其值”hello”在常量池中,str2使用new关键字创建了一个对象,在堆中开辟了空间,”==”比较的是对象的引用,即内存地址,所以str1与str2两个对象的内存地址是不相同的
2.Java语言中,String类中的indexOf()方法返回值的类型是()
选项 | 内容 |
---|---|
A | int32 |
B | int16 |
C | int |
D | long |
答案:C。语法bai为strObj.indexOf(subString[, startIndex])。
参数:
1、strObj:必选项du。String 对象或文字。
2、subString:必选项。要在 String 对象中查找的子字符串。
3、starIndex:可选项。该整数值指出在 String 对象内开始查找的索引。如果省略,则从字符串的开始处查。
3.给定以下代码,程序的运行结果是 ()
public class Example {
String str=new String("good");
char [] ch={'a','b','c'};
public static void main(String[] args) {
Example ex=new Example();
ex.change(ex.str, ex.ch);
System.out.print(ex.str+"and");
System.out.print(ex.ch);
}
public void change(String str,char ch[]){
str="test ok";
ch[0]='g';
}
}
答案:goodandgbc
分析:在方法调用时,在change方法中对str的值进行修改,是将str指向了常量江池中的”test ok”,而主方法中的ex.str仍然指向的是常量池中的”good”。字符型数组在方法调用时,将主方法中ex.ch的引用传递给change方法中的ch,指向是堆中的同一堆空间,所以修改ch[0]的时候,ex.ch可以看到相同的修改后的结果。
4.执行下列代码后,哪个结论是正确的()(选择两项)
String[] s=new String[10];
选项 | 内容 |
---|---|
A | s[10]为”” |
B | s[9]为null |
C | s[0]为未定义 |
D | s.length为10 |
答案:BD
分析: 引用数据类型的默认值均为null
s.length数组的长度
5.实现String类的replaceAll方法
思路说明:replaceAll方法的本质是使用正则表达式进行匹配,最终调用的其实是Matcher对象的replaceAll方法。
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TestStringReplaceAll {
public static void main(String[] args) {
String str = "a1s2d3f4h5j6k7";
// 将字符串中的数字全部替换为0
System.out.println(replaceAll(str, "\\d", "0"));
}
/**
* @param str:源字符串
* @param regex:正则表达式
* @param newStr:替换后的子字符串
* @return 返回替换成功后的字符串
*/
public static String replaceAll(String str, String regex, String newStr) {
Pattern pattern = Pattern.compile(regex);
Matcher mathcer = pattern.matcher(str);
String reslut = mathcer.replaceAll(newStr);
return reslut;
}
}
6.在“=”后填写适当的内容:
String []a=new String[10];
则:a[0]~a[9]=(空一);
a.length=10;
如果是int[]a=new int[10];
则:a[0]~a[9]= (空二)
a.length= (空三)
答案:null、0、10
7.是否可以继承String类?
答:不可以,因为String类有final修饰符,而final修饰的类是不能被继承的,实现细节不允许改变。
public final class String implements java.io.Serializable,
Comparable< String>, CharSequence
8.String类为什么是final的
答:1) 为了效率。若允许被继承,则其高度的被使用率可能会降低程序的性能。
2)为了安全。JDK中提供的好多核心类比如String,这类的类的内部好多方法的实现都不是java编程语言本身编写的,好多方法都是调用的操作系统本地的API,这就是著名的“本地方法调用”,也只有这样才能做事,这种类是非常底层的,和操作系统交流频繁的,那么如果这种类可以被继承的话,如果我们再把它的方法重写了,往操作系统内部写入一段具有恶意攻击性质的代码什么的,这不就成了核心病毒了么?不希望别人改,这个类就像一个工具一样,类的提供者给我们提供了, 就希望我们直接用就完了,不想让我们随便能改,其实说白了还是安全性,如果随便能改了,那么java编写的程序肯定就很不稳定,你可以保证自己不乱改, 但是将来一个项目好多人来做,管不了别人,再说有时候万一疏忽了呢?他也不是估计的, 所以这个安全性是很重要的,java和C++相比,优点之一就包括这一点。
9.给定两个字符串s和t, 写一个函数来决定是否t是s的重组词。你可以假设字符串只包含小写字母。
方法一:转为数组,利用现成的数组方法进行整理,再判断
class Solution {
public boolean isAnagram(String s, String t) {
char[] ss = s.toCharArray();//将s字符串转换为数组
char[] tt = t.toCharArray();//将t字符串转换为数组
if(ss.length != tt.length) return false;//长度不等,直接pass
Arrays.sort(ss);//排列组合
Arrays.sort(tt);
return Arrays.equals(ss,tt);//看他们各自拼接的组合有无相等的可能
}
}
方法二:用for遍历,直接判断ASCII码
public class Solution {
public boolean isAnagram(String s, String t) {
if(s.length()!=t.length())
return false;
int bit[] = new int[26];
for(int i=0;i<s.length();i++){
bit[s.charAt(i)-'a']++;
}
for(int i=0;i<s.length();i++){
if(--bit[t.charAt(i)-'a']<0)
return false;
}
return true;
}
}
附ASCII码表: http://ascii.911cha.com/.
10.String s=new String(“abc”);创建了几个String对象?
答: 两个或一个,”abc”对应一个对象,这个对象放在字符串常量缓冲区,常量”abc”不管出现多少遍,都是缓冲区中的那一个。New String每写一遍,就创建一个新的对象,它依据那个常量”abc”对象的内容来创建出一个新String对象。如果以前就用过’abc’,这句代表就不会创建”abc”自己了,直接从缓冲区拿。
11.输出结果?
String str1=“hello”;
Sring str2=“he”+new String(“llo”);
Sysem.out.println(str1==str2));
Sysem.out.println(str.equal(str2));
false
true
注:相似题目点击: https://blog.csdn.net/skisqibao/article/details/81155454.
12.下面哪个是正确的()
选项 | 内容 |
---|---|
A | String temp[ ] = new String{“a”,”b”,”c”}; |
B | String temp[ ] = {“a”,”b”,”c”}; |
C | String temp= {“a”,”b”,”c”}; |
D | String[ ] temp = {“a”,”b”,”c”}; |
答案:BD。数组的创建参见博文: https://blog.csdn.net/qq_44518192/article/details/107085678.
13.字符串如何转换为int类型
public class Test {
public static void main(String[] args) {
//方式一
int num=Integer.parseInt("123");
//方式二
int num2=Integer.valueOf("123");
System.out.println(num+" "+num2);
}
}
14.写一个方法,实现字符串的反转,如:输入abc,输出cba
public class Test {
public static void main(String[] args) {
String result=reverse("abc");
System.out.println(result);
}
public static String reverse(String str){
StringBuilder result=new StringBuilder("");
char[] chArra=str.toCharArray();
for(int i=chArra.length-1;i>=0;i--){
char ch=chArra[i];
result.append(ch);
}
return result.toString();
}
}
在网上发现一篇写的不错的360文档,点击查看: http://www.360doc.com/content/10/0628/22/380362_35815752.shtml.
15.编写java,将“I follow Bill Gate.Tom Gate.John Gate”中的“Gate”全部替换为“Gates”
public classDemo1 {
publicstaticvoid main(String[] args) {
String s="I follow Bill Gate.Tom Gate.John Gate";
System.out.println(s);
s=s.replaceAll("Gate","Gates");
System.out.println(s);
}
}
16.String 是最基本的数据类型吗?
答: 不是 。Java中的基本数据类型只有8个:byte、short、int、long、float、double、char、boolean;除了基本类型(primitive type)和枚举类型(enumeration type),剩下的都是引用类型(reference type)。
17.String 和StringBuilder、StringBuffer 的区别?
答: Java 平台提供了两种类型的字符串:String和StringBuffer / StringBuilder
相同点:
它们都可以储存和操作字符串,同时三者都使用final修饰,都属于终结类不能派生子类,操作的相关方法也类似例如获取字符串长度等;
不同点:
其中String是只读字符串,也就意味着String引用的字符串内容是不能被改变的,而StringBuffer和StringBuilder类表示的字符串对象可以直接进行修改,在修改的同时地址值不会发生改变。StringBuilder是JDK 1.5中引入的,它和StringBuffer的方法完全相同,区别在于它是在单线程环境下使用的,因为它的所有方面都没有被synchronized修饰,因此它的效率也比StringBuffer略高。在此重点说明一下,String、StringBuffer、StringBuilder三者类型不一样,无法使用equals()方法比较其字符串内容是否一样!
补充1:有一个面试题问:有没有哪种情况用+做字符串连接比调用StringBuffer / StringBuilder对象的append方法性能更好?答:如果连接后得到的字符串在静态存储区中是早已存在的,那么用+做字符串连接是优于StringBuffer / StringBuilder的append方法的。
补充2:下面也是一个面试题,问程序的输出,看看自己能不能说出正确答案。
package com.bjsxt;
public class smallT {
public static void main(String[] args) {
String a = "Programming";
String b = new String("Programming");
String c = "Program" + "ming";
System.out.println(a == b);
System.out.println(a == c);
System.out.println(a.equals(b));
System.out.println(a.equals(c));
System.out.println(a.intern() == b.intern());
}
}
解析:
String类存在intern()方法,含义如下:返回字符串对象的规范化表示形式。它遵循以下规则:对于任意两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern()
才为 true。
字符串比较分为两种形式,一种使用比较运算符”==”
比较,他们比较的是各自的字符串在内存当中的地址值是否相同;一种是使用equals()方法进行比较,比较的是两个字符串的内容是否相同!
结果如下:
a == b-->false
a == c-->true
a.equals(b)-->true
a.equals(c)-->true
a.intern() == b.intern()-->true
对应 内存模型 图:
18.String s=“Hello”;s=s+“world!”;执行后,是否是对前面s指向空间内容的修改?
答:不是对前面s指向空间内容的直接修改。
因为String被设计成不可变(immutable)类,所以它的所有对象都是不可变对象。在这段代码中,s原先指向一个String对象,内容是 “Hello”,然后我们对s进行了+操作,那么s所指向的那个对象是否发生了改变呢?答案是没有。这时,s不指向原来那个对象了,而指向了另一个 String对象,内容为"Hello world!",原来那个对象还存在于内存之中,只是s这个引用变量不再指向它了。
通过上面的说明,我们很容易导出另一个结论,如果经常对字符串进行各种各样的修改,或者说,不可预见的修改,那么使用String来代表字符串的话会引起很大的内存开销。因为 String对象建立之后不能再改变,所以对于每一个不同的字符串,都需要一个String对象来表示。这时,应该考虑使用StringBuffer类,它允许修改,而不是每个不同的字符串都要生成一个新的对象。并且,这两种类的对象转换十分容易。
同时,我们还可以知道,如果要使用内容相同的字符串,不必每次都new一个String。例如我们要在构造器中对一个名叫s的String引用变量进行初始化,把它设置为初始值,应当这样做:
public class Demo {
private String s;
...
public Demo {
s = "Initial Value";
}
...
}
而非s = new String("Initial Value");
后者每次都会调用构造器,生成新对象,性能低下且内存开销大,并且没有意义,因为String对象不可改变,所以对于内容相同的字符串,只要一个String对象来表示就可以了。也就说,多次调用上面的构造器创建多个对象,他们的String类型属性s都指向同一个对象。
上面的结论还基于这样一个事实:对于字符串常量,如果内容相同,Java认为它们代表同一个String对象。而用关键字new调用构造器,总是会创建一个新的对象,无论内容是否相同。
至于为什么要把String类设计成不可变类,是它的用途决定的。其实不只String,很多Java标准类库中的类都是不可变的。在开发一个系统的时候,我们有时候也需要设计不可变类,来传递一组相关的值,这也是面向对象思想的体现。不可变类有一些优点,比如因为它的对象是只读的,所以多线程并发访问也不会有任何问题。当然也有一些缺点,比如每个不同的状态都要一个对象来代表,可能会造成性能上的问题。所以Java标准类库还提供了一个可变版本,即 StringBuffer。参见《Thinking in Java》第370-380页。
19.String s = new String(“xyz”);创建几个String Object?
答:两个或一个,”xyz”对应一个对象,这个对象放在字符串常量缓冲区,常量”xyz”不管出现多少遍,都是缓冲区中的那一个。New String每写一遍,就创建一个新的对象,它依据那个常量”xyz”对象的内容来创建出一个新String对象。如果以前就用过’xyz’,这句代表就不会创建”xyz”自己了,直接从缓冲区拿。
20.下面这条语句一共创建了多少个对象:String s=“a”+“b”+“c”+“d”;
答:对于如下代码:
String s1 = "a";
String s2 = s1 + "b";
String s3 = "a" + "b";
System.out.println(s2 == "ab");
System.out.println(s3 == "ab");
第一条语句打印的结果为false,第二条语句打印的结果为true,这说明javac编译可以 对字符串常量直接相加的表达式进行优化,不必要等到运行期去进行加法运算处理,而是在编译时去掉其中的加号,直接将其编译成一个这些常量相连的结果。
题目中的第一行代码被编译器在编译时优化后,相当于直接定义一个”abcd”的字符串,所以,上面的代码应该只创建了一个String对象。
写如下两行代码,
String s = "a" + "b" + "c" + "d";
System.out.println(s == "abcd");
最终打印的结果应该为true。