Java字符串与数组
问题及答案来源⾃《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⽅法实际使⽤:
1class Person{
2
3 }
4
5public class ObjectDemo {
6public static void main(String[] args) {
7// Person类没有重写equals⽅法⽽Object类中的equals⽅法是⽐较两个对象的地址
8 Person p1 = new Person();
9 Person p2 = new Person();
10 System.out.println(p1.equals(p2)); // false
11
java定义一维数组并赋值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第⼀组: 判断⽅法
3boolean equals(String str); // ⽐较两个字符串的内容是否相等
4boolean equalsIgnoreCase(String str); // ⽐较两个字符串的内容是否相等(忽略⼤⼩写)
5boolean startsWith(String subStr); // 判断某个字符串是否以指定的⼦串开头
6boolean endsWith(String subStr): // 判断某个字符串是否以指定的⼦串结尾
7
8第⼆组: 获取⽅法
9int length(); // 获取字符串中字符个数
10char charAt(int index); // 谋取字符串某⼀个字符(指定下标)
11 String subString(int startIndex); // 从指定下标开始截取字符串,直到字符串末尾
12 String subString(int startIndex, int endIndex); // 从指定下标开始截取字符串,到指定下标结束(左闭右开)
13int 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 = new StringBuffer(s);
5 sb.append(" World");
6 s = sb.toString();
StringBuilder和StringBuffer:
StringBuilder也是可以被修改的字符串,它与StringBuffer类似,都是字符串缓冲区,但是StringBuilder
不是线程安全的,如果只是在单线程中使⽤字符串缓冲区,那么StringBuilder的效率会更⾼些
⽽StringBuffer在必要时可以对⽅法进⾏同步,所以任意特定实例上的操作就好像是以串⾏顺序
发⽣,该顺序与所涉及的每个线程进⾏的⽅法调⽤顺序⼀致
因此在只有单线程访问时可以使⽤StringBuilder,当有多个线程访问时最好⽤线程安全的StringBuffer
StringTokenizer:
StringTokenizer是⽤来分割字符串的⼯具类,⽰例如下:
1public class Demo{
2public static void main(String[] args) {
3 StringTokenizer st = new StringTokenizer("Welcome to our country");
4while(st.hasMoreTokens()){
5 System.out.Token());
6 }
7 }
8 }
输出结果:
Welcome
to
our
country
总结:
在执⾏效率⽅⾯,StringBuilder最⾼,StringBuffer次之,String最低,使⽤如下:
如果操作的数据量⽐较⼩,应优先使⽤String类
如果是在单线程下操作⼤量数据应优先使⽤StringBuilder类
如果是在多线程下操作⼤量数据应优先使⽤StringBuffer类
4、Java中数组是不是对象?
数组是指具有相同类型的数据的集合,它们⼀般具有固定的长度,并且在内存中占据连续的空间在C/C++中,数组名只是⼀个指针,这个指针指向了数组的⾸元素,没有属性也没有⽅法
⽽在Java中,数组不仅具有⾃⼰的属性,还有⽅法可以调⽤,故在Java中数组是对象
每个数组类型都有其对于的类型,可以通过instanceof来判断数据的类型,如下:
1public class FindLeftAndRightBigger {
2public static void main(String[] args) {
3int[] a = {1, 2, 3};
4int[][] b = new int[2][3];
5 String[] s = {"asfd", "saf"};
6if(a instanceof int[]){
7 System.out.println("int[]");
8 }
9if(b instanceof int[][]){
10 System.out.println("int[][]");
11 }
12if(s instanceof String[]){
13 System.out.println("String[]");
14 }
15 }
16 }
17// 输出结果:
18// int[]
19// int[][]
5、Java数组的初始化⽅法有哪⼏种?
Java数组的初始化⽅法如下:
1// ⼀维数组声明:
2 type arrayName[] 或 type[] arrayName
3// ⼆维数组声明:
4 type arrayName[][] 或 type[][] arrayName 或 type[] arrayName[]
5// 数组初始化:可以在声明时直接赋值也可以在之后new
6// 注:type既可以是基本数据类型也可以是类
7
8// ⼀维数组初始化实例:
9int[] a = new int[5]; // 动态创建了⼀个包含5个整形值得数组,默认值为0
10int[] a = {1, 2, 3}; // 声明⼀个数组并初始化
11
12// ⼆维数组初始化实例:
13// Java中⼆维数组的第⼆维长度可以不同
14int[][] arr = {{1, 2}, {3, 4, 5}};
15int[][] arr = new int[2][];
16 arr[0] = new int[]{1, 2};
17 arr[1] = new int[]{3, 4, 5};
注:原⽣类指未被实例化的类,数组是实例化、被分配空间的类,数组不属于原⽣类
6、length属性和length()⽅法有什么区别?
length属性:获取数组长度
length⽅法:计算字符串长度
1public class test{f
2public static void testArray(int[] arr){
3 System.out.println("数组长度为" + arr.length);
4 }
5
6public static void testString(String s){
7 System.out.println("字符串长度为" + s.length());
8 }
9
10public static void main(String[] args) {
11 testArray(new int[]{1, 2, 3}); // 3
12 testString("hello"); // 5
13 }
14 }
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论