赞
踩
问题及答案来源自《Java程序员面试笔试宝典》第四章 Java基础知识 4.5字符串与数组
1、字符串创建与存储的机制是什么?
Java中字符串声明与初始化主要有两种情况:
(1)String s1 = new String("abc")与String s2 = new String("abc")语句
执行String s1 = new String("abc")语句,字符串池中不存在"abc",则会创建一个字符串常量"abc",
并将它添加到字符串常量池中,然后new String()会在堆中创建一个新的对象,s1指向堆中的String对象
紧接着创建String s2 = new String("abc")语句,因为字符串常量池中已经有了字符串常量"abc",所以
不会再创建"abc",直接new String()在堆中创建一个新的对象,然后使用s2指向这个对象
s1与s2指向堆中的不同String对象,地址自然也不相同
(2)String s1 = "abc"语句与String s2 = "abc"语句
在JVM中存在着一个字符串常量池,其中保存了着很多String 对象,s1,s2引用的是同一个常量池中的对象。
当创建一个字符串常量时,例如String s1 = "abc",会首先在字符串常量池中查找是否已经有相同的字符串被定义,
若已经定义,则直接获取对其的引用,此时不需要创建字符串常量"abc",如果没有定义,则首先创建字符串常量
"abc",然后把它加入到字符串池中,再将引用返回
例子1:
String s1 = new String("abc"); // 先查找常量区有无"abc"常量,若无则将其"abc"添加到常量区,再在堆中创建对象,将s1指向堆中的对象
String s2 = new String("abc"); // 发现在常量区已经有了"abc",在堆中创建对象,将s2指向堆中的对象
例子2:
String s1 = "abc"; // 在常量区里面创建一个"abc"字符串对象,s1获取对其的引用
String s2 = "abc"; // 发现在常量区已经有了"abc",s2直接获取对其的引用
引申 - 对于String类型的变量s,赋值语句s=null和赋值语句s=""有什么区别?
s=null,是指s不指向任何一个字符串;s=""中的s指向空字符串
笔试题 - new String("abc")创建了几个对象?
一个或两个,如果常量池中原来就有"abc",那么只创建一个对象,否则创建两个对象
2、==、equals和hashCode有什么区别?
==:是运算符,用于比较两个变量是否相等。当比较对象时,比较的是对象在内存中的地址
equals方法:用于比较两个对象是否相等,默认Object类的equals方法是比较两个对象的地址,跟==的结果一样
如果一个类没有自己定义equals方法,它默认的equals方法就是使用"=="运算符,也就是在比较两个变量指向
的对象是否是同一个对象
hashCode方法:是用来鉴定两个对象是否相等,默认Object类中的hashCode方法返回对象在内存中地址转换成
的一个int值,所以如果没有重写hashCode()方法,任何对象的hashCode()方法都是不相等的。返回一个离散的int型整数。
在集合类操作中使用,为了提高查询速度。(HashMap,HashSet等)
equals方法实际使用:
1 classPerson{2
3 }4
5 public classObjectDemo {6 public static voidmain(String[] args) {7 //Person类没有重写equals方法 而Object类中的equals方法是比较两个对象的地址
8 Person p1 = newPerson();9 Person p2 = newPerson();10 System.out.println(p1.equals(p2)); //false11
12 //String中重写了equals方法 比较的是两个字符串的内容
13 String s1 = new String("hello");14 String s2 = new String("hello");15 System.out.println(s1.equals(s2)); //true
16
17 String s3 = "hello";18 String s4 = "hello";19 System.out.println(s3.equals(s4)); //true
20 }21 }
java中的数据类型,可分为两类:
(1)基本数据类型
Java中基本数据类型有八种:byte,short,char,int,long,float,double,boolean,
他们之间的比较,用双等号(==),比较的是他们的值。
(2)复合数据类型(类)
当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址,所以,除非是同一个new
出来的对象,他们的比较后的结果为true,否则比较后结果为false。
在Java的Object中的基类中定义了一个equals的方法,这个方法的初始行为是比较对象的内存地址,
但在一些类库当中这个方法被覆盖掉了,如String等,在这些类当中equals有其自身的实现,而不再是
比较对象的内存地址了
equals方法和hashCode方法的关系(用于set、map):
hashCode方法只有在set或map集合中用到
当覆盖了equals方法时,比较对象是否相等将通过覆盖后的equals方法进行比较(判断对象的内容是否相等)
将对象放入到集合中时,首先判断要放入对象的hashCode值与集合中的任意一个元素的hashCode值是否相等,
如果不相等直接将该对象放入集合中。如果hashCode值相等,然后再通过equals方法判断要放入对象与集合中的
任意一个对象是否相等,如果equals判断不相等,直接将该元素放入到集合中,否则不放入。
3、String、StringBuffer、StringBuilder和SringTokenizer有什么区别?
Java中有5个类可以对字符或字符串进行操作,分别是Character、String、StringBuffer、StringBuilder
和SringTokenizer,其中Character用于单个字符操作,String用于字符串操作(属于不可变类),而
StringBuffer也是用于字符串操作(属于可变类)
Character的API:
boolean isDigit(char ch) 确定指定字符是否为数字。
boolean isLowerCase(char ch) 确定是否是小写字母字符
boolean isUpperCase(char ch) 确定是否大写字母字符
char toLowerCase(char ch) 将给定字符转换成大写字符
char toUpperCase(char ch) 将给定字符转换成小写字符
String的API:
1 引用类型String中的方法(4532)2 第一组: 判断方法3 boolean equals(String str); //比较两个字符串的内容是否相等
4 boolean equalsIgnoreCase(String str); //比较两个字符串的内容是否相等(忽略大小写)
5 boolean startsWith(String subStr); //判断某个字符串是否以指定的子串开头
6 boolean endsWith(String subStr): //判断某个字符串是否以指定的子串结尾
7
8 第二组: 获取方法9 int length(); //获取字符串中字符个数
10 char charAt(int index); //谋取字符串某一个字符(指定下标)
11 String subString(int startIndex); //从指定下标开始截取字符串,直到字符串末尾
12 String subString(int startIndex, int endIndex); //从指定下标开始截取字符串,到指定下标结束(左闭右开)
13 int indexOf(String subStr); //获取子串第一次出现的下标
14
15 第三组: 转换方法16 String toLowerCase(); //转成小写串
17 String toUpperCase(); //转成大写串
18 Char[] toCharArray(); //变成字符数组
19
20 第四组: 其他方法21 String trim(); //去掉字符串两端的空格
22 String[] split(String str); //切割字符串
String和StringBuffer的区别:
String是不可变类,一旦对象创建其值将不能改变,而StringBuffer是可变类,对象创建后值可以改变
实例化String时可以用赋值也可以用new初始化,而实例化StringBuffer只能用new初始化
String字符串修改的原理:
当用String类型来对字符串进行修改时,其实现方法是首先创建一个StringBuffer对象,然后调用StringBuffer的
append方法,最后调用StringBuffer的toString方法把结果返回
1 String s = "Hello";2 s += " World";3 //以上代码等价于
4 StringBuffer sb = newStringBuffer(s);5 sb.append(" World");6 s = sb.toString();
StringBuilder和StringBuffer:
StringBuilder也是可以被修改的字符串,它与StringBuffer类似,都是字符串缓冲区,但是StringBuilder
不是线程安全的,如果只是在单线程中使用字符串缓冲区,那么StringBuilder的效率会更高些
而StringBuffer在必要时可以对方法进行同步,所以任意特定实例上的操作就好像是以串行顺序
发生,该顺序与所涉及的每个线程进行的方法调用顺序一致
因此在只有单线程访问时可以使用StringBuilder,当有多个线程访问时最好用线程安全的StringBuffer
StringTokenizer:
StringTokenizer是用来分割字符串的工具类,示例如下:
1 public classDemo{2 public static voidmain(String[] args) {3 StringTokenizer st = new StringTokenizer("Welcome to our country");4 while(st.hasMoreTokens()){5 System.out.println(st.nextToken());6 }7 }8 }
输出结果:
Welcome
to
our
country
总结:
在执行效率方面,StringBuilder最高,StringBuffer次之,String最低,使用如下:
如果操作的数据量比较小,应优先使用String类
如果是在单线程下操作大量数据应优先使用StringBuilder类
如果是在多线程下操作大量数据应优先使用StringBuffer类
4、Java中数组是不是对象?
数组是指具有相同类型的数据的集合,它们一般具有固定的长度,并且在内存中占据连续的空间
在C/C++中,数组名只是一个指针,这个指针指向了数组的首元素,没有属性也没有方法
而在Java中,数组不仅具有自己的属性,还有方法可以调用,故在Java中数组是对象
每个数组类型都有其对于的类型,可以通过instanceof来判断数据的类型,如下:
1 public classFindLeftAndRightBigger {2 public static voidmain(String[] args) {3 int[] a = {1, 2, 3};4 int[][] b = new int[2][3];5 String[] s = {"asfd", "saf"};6 if(a instanceof int[]){7 System.out.println("int[]");8 }9 if(b instanceof int[][]){10 System.out.println("int[][]");11 }12 if(s instanceofString[]){13 System.out.println("String[]");14 }15 }16 }17 //输出结果:18 //int[]19 //int[][]
5、Java数组的初始化方法有哪几种?
Java数组的初始化方法如下:
1 //一维数组声明:
2 type arrayName[] 或 type[] arrayName3 //二维数组声明:
4 type arrayName[][] 或 type[][] arrayName 或 type[] arrayName[]5 //数组初始化:可以在声明时直接赋值也可以在之后new6 //注:type既可以是基本数据类型也可以是类7
8 //一维数组初始化实例:
9 int[] a = new int[5]; //动态创建了一个包含5个整形值得数组,默认值为0
10 int[] a = {1, 2, 3}; //声明一个数组并初始化11
12 //二维数组初始化实例:13 //Java中二维数组的第二维长度可以不同
14 int[][] arr = {{1, 2}, {3, 4, 5}};15 int[][] arr = new int[2][];16 arr[0] = new int[]{1, 2};17 arr[1] = new int[]{3, 4, 5};
注:原生类指未被实例化的类,数组是实例化、被分配空间的类,数组不属于原生类
6、length属性和length()方法有什么区别?
length属性:获取数组长度
length方法:计算字符串长度
1 public classtest{f2 public static void testArray(int[] arr){3 System.out.println("数组长度为" +arr.length);4 }5
6 public static voidtestString(String s){7 System.out.println("字符串长度为" +s.length());8 }9
10 public static voidmain(String[] args) {11 testArray(new int[]{1, 2, 3}); //3
12 testString("hello"); //5
13 }14 }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。