1. Java String、StringBuffer和StringBuilder类
String类是不可变类,即一旦一个String对象被创建以后,包括在这个对象中的字符序列是不可改变的,直至这个对象被销毁。
StringBuffer对象则代表一个字符序列可变的字符串,当一个StringBuffer被创建以后,通过StringBuffer提供的append()、insert()、reverse()、setCharAt()、setLength()等方法可以改变这个字符串对象的字符序列。可以调用toString()方法将其转换为一个String()对象StringBuffer是线程安全的,StringBuilder则没有实现线程安全功能,所以性能略高。如果需要创建一个内容可变的字符串对象,则应该优先考虑使用StringBuilder类。
String、StringBuffer和StringBuilder都实现了CharSequence接口,该接口可认为是一个字符串的协议接口。
一、String类提供了大量构造器来创建String对象:
- String():创建一个包含0个字符串序列的String对象(并不是返回null)
- String(byte[] bytes, Charset charset):使用指定的字符集将指定的byte[]数组解码成一个新的String对象
- String(byte[] bytes, int offset, int length):使用平台的默认字符集将指定的byte[]数组从offset开始、长度为Length的子数组解码成一个新的String对象
- String(byte[] bytes, int offset, int length, String charsetName):使用指定的字符集将指定的byte[]数组从offset开始、长度为Length的子数组解码成一个新的String对象
- String(byte[] bytes, String charsetName):使用指定的字符集将指定的byte[]数组解码成一个新的String对象
- String(char[] value, int offset, int count):将指定的字符数组从offset开始、长度为count的字符元素连缀成字符串
- String(String original):根据字符串直接量来创建一个String对象。新创建的String对象是该参数字符串的副本
- String(StringBuffer buffer):根据StringBuffer对象来创建对应的String对象
String(StringBuilder builder):根据StringBuilder对象来创建对应的String对象
二、操作字符串对象的方法
char charAt(int index):获取字符串中的某一个字符,其中的参数 index 指的是字符串中序数。字符串的序数从0开始到length()-1
int compareTo (String anotherString ):当前String对象与anotherString比较 。相等返回0;不相等 时,从两个字符串第 0 个字符开始比较,返回第一个不相等的字符差,另一种情况,较长字符串的前面部分恰巧是较短的字符串,返回它们的长度差
String a1 = new String(“abcdefghijklmn”);
String a2 = new String(“abcdefghij”);
String a3 = new String(“abcdefghijalmn”);
System.out.println(“a1.compareTo(a2):”+a1.compareTo(a2)); //返回长度差 4
System.out.println(“a1.compareTo(a3):”+a1.compareTo(a3)); //返回’k’-‘a’的差 10- String concat(String str):将该String对象与str 连接在一起。通过“+”串联更方便
- boolean contentEquals(StringBuffer sb):将该 String对象与StringBuffer的对象sb进行比较。相等返回 true
- static String copyValueOf(char[] data):将字符数组连缀成字符串,与String(char[] content)构造器的功能相同
- static String copyValueOf(char[] data, int offset, int count):将char数组的子数组中的元素连缀成字符串,与String(char[] value, int offset, int count)构造器的功能相同
boolean endsWith(String suffix):返回该字符串是否以suffix结尾
String f1 = “www.ishuhui.com”;
String f2= “com”;
System.out.println(“f1.endsWith(f2):” + f1.endsWith(f2)); //true- boolean equals(Object anObject):当anObject不为空并且与当前String对象一样,返回 true;否则,返回 false
- boolean equalsIgnoreCase(String string):比较字符串与another是否一样(忽略大小写)
- byte[] getBytes(String charsetName):将该String对象转换成byte数组
- byte[] getBytes(Charset charset):使用指定字符集,将该String对象转换成byte数组
- byte[] getBytes():将该String对象转换成byte数组,使用默认字符集
void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin):将字符串中从srcBegin开始,到srcEnd结束的字符负责到dst字符数组中,其中dstBegin为目标字符数组的起始复制位置
char[] c1 = {‘L’,’I’,’N’,’ ‘,’B’,’o’,’K’,’a’,’i’};
String s8 = new String(“Me “);
s8.getChars(0, 3, c1, 0);
System.out.println(c1);- int hashCode ():返回当前字符的哈希表码
- int indexOf(int c):找出c字符在该字符串中第一次出现的位置
- int indexOf(int c, int fromIndex):找出c字符在该字符串中从fromIndex开始后第一次出现的位置
- int indexOf(String substr):找出substr子字符串在该字符串中第一次出现的位置
- int indexOf(String substr, int fromIndex):找出substr子字符串中从fromIndex开始后在该字符串中第一次出现的位置
- boolean isEmpty():如果字符串的长度为0,则返回 true
- int lastindexOf(int c):找出c字符在该字符串中最后一次出现的位置
- int lastindexOf(int c, int fromIndex):找出c字符在该字符串中从fromIndex开始后最后一次出现的位置
- int lastindexOf(String substr):找出substr子字符串在该字符串中最后一次出现的位置
- int lastindexOf(String substr, int fromIndex):找出substr子字符串中从fromIndex开始后在该字符串中最后一次出现的位置
- int length():返回字符串的字符个数
- String replace(char oldChar, char newChar):将字符串中的第一个oldChar替换成newChar
- boolean startsWith(String prefix):该String对象是否以prefix开始
- boolean startsWith(String prefix, int toffset):该String对象从toffse 位置算起,是否以 prefix开始
- String substring(int beginIndex):取从beginIndex位置开始到结束的子字符串
- String substring(int beginIndex, int endIndex)取从beginIndex位置开始到endIndex位置结束的子字符串
- char[] toCharArray():将该String对象转换成char数组
- String toLowerCase():将字符串转换成小写
- String toUpperCase():将字符串转换成大写
- String trim():移除字符串中的空格
static String valueOf(X x):将基本类型值转换成字符串的方法
三、String类是不可变的,String的实例一旦生成就不会再改变
String str1 = “java”;
str1 = str1 + “struts”;
str1 = str1 + “spring”;上面程序除了使用了3个字符串直接量之外,还会额外生成2个字符串直接量”javastruts”和”javastrutsspring”,程序中的str1依次指向3个不同的字符串对象
因为String是不可变的,所以会产生很多临时变量,使用StringBuffer和StringBuilder就可以避免这个问题。
public class StringBuilderTest
{
public static void main(String[] args)
{
StringBuilder sb = new StringBuilder();
// 追加字符串
sb.append("java");//sb = "java"
// 插入
sb.insert(0 , "hello "); // sb="hello java"
// 替换
sb.replace(5, 6, ","); // sb="hello, java"
// 删除
sb.delete(5, 6); // sb="hellojava"
System.out.println(sb);
// 反转
sb.reverse(); // sb="avajolleh"
System.out.println(sb);
System.out.println(sb.length()); // 输出9
System.out.println(sb.capacity()); // 输出16
// 改变StringBuilder的长度,将只保留前面部分
sb.setLength(5); // sb="avajo"
System.out.println(sb);
}
}
2. Java中各种数字类型转换成字符串型
一、Java中各种数字类型转换成字符串型:
String s = String.valueOf( value); // 其中 value 为任意一种数字类型。
二、字符串型转换成各种数字类型:
String str = “120”;
byte b = Byte.parseByte( str );
short t = Short.parseShort( str );
int i = Integer.parseInt( str );
long l = Long.parseLong( str );
Float f = Float.parseFloat( str );
Double d = Double.parseDouble( str );
三、数字类型与数字类对象之间的转换:
byte b = 120;
Byte bo = new Byte( b );
b = bo.byteValue();
short t = 120;
Short to = new Short( t );
t = to.shortValue();
int i = 169;
b = bo.byteValue();
short t = 169;
Short to = new Short( t );
t = to.shortValue();
int i = 169;
Integer io = new Integer( i );
i = io.intValue();
long l = 169;
Long lo = new Long( l );
l = lo.longValue();
float f = 169f;
Float fo = new Float( f );
f = fo.floatValue();
double d = 169f;
Double dObj = new Double( d );
d = dObj.doubleValue();
3. 基础tcp/ip知识
面试过程中,相对算法/操作系统/数据库部分,网络方面的知识可能算是比较简单的了。本文主要讲述TCP/IP协议的基础知识,描述的比较浅,先做一个铺垫,网络方面的具体知识比如:iptable/nmap/curl/ssh和sql注入攻击等我将在以后结合Linux补充几篇博文来描述。
一、描述一下TCP三次握手的过程
接下来我们根据下面这幅图来解释一下TCP三次握手。p.s: 每个箭头代表一次握手。
第一次握手
client(客户端)发送一个SYN(seq=x)包给server(服务器),然后“期待”server的ACK回复。p.s: seq为sequence(序列)的缩写,ACK为acknowledge(通知)的缩写。
第二次握手
1.server(服务器)接收到SYN(seq=x)包后就返回一个ACK(ack=x+1)包,意思是告诉client(客户端):我已经成功接收到你的SYN包。
2.并且自己也发送一个SYN(seq=y)包,然后”期待“client(客户端)的ACK回复
第三次握手
1.client(客户端)接收到server(服务器)发回的ACK(ack=x+1)包后,然后就把自己的状态设置为ESTABLISHED(已建立连接)。
二、分析一下TCP四次挥手的整个过程
以上面这张图为例,我们来分析一下TCP四次挥手的过程
第一次挥手
client(客户端)发送一个FIN(seq=x+2&&ack=y+1)包,此时client进入FIN_WAIT_1状态,这表明client已经没有数据要发送了。
第二次挥手
server(服务器)收到了client(客户端)发来的FIN(seq=x+2&&ack=y+1)包后,向client(客户端)发回一个ACK(ack=x+3)包,此时client进入FIN_WAIT_2状态,这表明server已经”同意”client的挥手请求。
第三次挥手
server(服务器)向client(客户端)发送FIN(seq=y+1)包,请求关闭连接,同时server进入LAST_ACK状态。
第四次挥手
client(客户端)收到server(服务器)发送的FIN(seq=y+1)包。然后向server发送ACK(ack=y+2)包,此时client进入TIME_WAIT状态。server收到client的ACK(ack=y+2)包以后,正式关闭连接;client等待一段时间还没有得到回复后判断server(服务器)已正常关闭,于是将自己的连接也正式关闭。
关于TCP滑窗/阻塞处理等问题,以后我会继续在这篇文章下面补充。
三、谈一谈TCP/UDP的区别和优缺点
- TCP协议是可靠的而且面向连接,它可以保证信息到达的顺序,UDP和IP协议都是不可靠的协议。
- TCP面向字节流,UDP面向报文。
- TCP数据传输慢,UDP数据传输快成本低,早期的QQ就是采用的UDP。
四、说一下计算机之间通信的原理
计算机之间是通过ip和port(端口)来进行通信的,每一台计算都具有一个独立ip地址(在浏览器里面输入ip.cn就可以查看你独有的公网ip地址),和65535个port(端口)。计算机每一个通过网络通信的程序都占有一个独立的port,通过ip我们能确定要访问的计算机,而port(端口)帮助我们要和计算机上的哪一个程序通信。
p.s: 在linux/mac上我们可以通过netstat命令查看本机上哪些端口被占用了。比如在我的计算机上,MySQL占用了3306,Tomcat占用了8080,Nginx占用了80,DNS服务器占用了53,Shadowsocks占用了1080,Privoxy占用了8118。
计算机之间是通过ip和port(端口)来进行通信的,每一台计算都具有一个独立ip地址(在浏览器里面输入ip.cn就可以查看你独有的公网ip地址),和65535个port(端口)。计算机每一个通过网络通信的程序都占有一个独立的port,通过ip我们能确定要访问的计算机,而port(端口)帮助我们要和计算机上的哪一个程序通信。
p.s: 在linux/mac上我们可以通过netstat命令查看本机上哪些端口被占用了。比如在我的计算机上,MySQL占用了3306,Tomcat占用了8080,Nginx占用了80,DNS服务器占用了53,Shadowsocks占用了1080,Privoxy占用了8118。
localhost :: ~ » netstat -tuln
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
tcp 0 0 127.0.1.1:53 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:53 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:8118 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:1080 0.0.0.0:* LISTEN
tcp6 0 0 :::21 :::* LISTEN
tcp6 0 0 ::1:53 :::* LISTEN
tcp6 0 0 :::22 :::* LISTEN
udp 0 0 127.0.0.1:1080 0.0.0.0:*
udp 0 0 127.0.1.1:53 0.0.0.0:*
udp 0 0 127.0.0.1:53 0.0.0.0:*五、谈一谈ip地址的分类
Class 开始地址 结束地址 网络地址位数 剩余位数 网络数
A类地址 0.0.0.0 127.255.255.255 8 24 128
B类地址 128.0.0.0 191.255.255.255 16 16 16,384
C类地址 192.0.0.0 223.255.255.255 24 8 2,097,152
D类地址 224.0.0.0 239.255.255.255 未定义 未定义 未定义
E类地址 240.0.0.0 255.255.255.255 未定义 未定义 未定义关于arp, ip header, tcp header, routing table等问题,以后我会继续在这篇文章下面补充。
六、说一说常见的服务以及它们对应的默认端口
端口 服务
21 FTP
22 SSH
25 Telnet
53 DNS
80 HTTP服务
443 HTTPS服务
1080 Shadowsocks
1521 Oracle
3306 MySQL七、描述一下在浏览器中输入url后整个响应过程
下面我们以我们在浏览器中输入segmentfault.com为例子来讲解。
- 查找域名(segmentfault.com)对应的IP地址。在linux/mac下可以通过dig命令来查询。
- 浏览器根据查询到的IP地址向segmentfault服务器的80端口发送一个HTTP请求(request)
- 后台PHP接收到请求(request)后,发回一个网页。
- 浏览器收到回复后,解析返回的网页。
上面只是简要的描述,如果要详细展开的话在实在太大了。面试过程中,应该详细描述DNS解析域名的过程,对于浏览器发送的request和response的整个流程可以结合TCP/IP四层模型和OSI七层模型来展开,而对于服务器是如何处理请求的,可以根据网站采用的后台框架详细展开描述。
八、介绍一下TCP/IP四层模型和OSI七层模型