关于同步方法的总结:
1.同步方法仍然涉及到同步监视器,只是不需要我们显示的声明。
2.非静态的同步方法,同步监视器是:this,当前类的对象
静态的额同步方法,同步监视器是:当前类本身
- 字符串相关的类
- JDK 8之前的日期时间API
- JDK8中新日期时间API
- Java比较器
- System类
- Math类
- BigInteger与BigDecimal
String
1.字符串,使用一对”“引起来表示
2.String声明为为final,不可被继承
3.String实现了Serializable接口:表示字符串是支持序列化的
实现了Comparable接口:表示String可以比较大小
4.String内部定义了final char[] value用于存储字符串数据
5.String:代表不可变的字符序列。简称:不可变性字符串常量池中
6.字符串常量池中是不会存储相同内容的字符串的
7.通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中
8.字符串常量池中是不会存储相同的字符串值
体现:1.当对字符串重新赋值时,需要重新写指定内存区域赋值,不能使用原有的value进行操作
2.当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行操作
3.当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域
import org.junit.Test;
public class StringTest {
@Test
public void test1(){
String s1="abc";
String s2="abc";
s1="hello";
System.out.println(s1);
System.out.println(s2);
System.out.println(s1 == s2);
}
}
IDEA如何导入junitjar包
file---->projectStructure—>Modules---->Deprndencies—>+号 去IDEA安装目录下的lib下寻找junit-4.12.jar和hamcrest-core-1.3.jar
只导入junit-4.12.jar测试方法报错 NoClassDefFoundError
String的实例化方式:
方式一:通过字面量定义的方式 在方法区中的字符串常量池中
方式二:通过new+构造器的方式 是数据在堆空间中开辟空间以后对应的地址值
面试题:String s=new String(“abc”);创建对象,在内存中创建了几个对象
两个:一个是堆空间中的new结构,另一个是char[]对应的常量池中的数据:“abc”
常量与常量的拼接结果在常量池中。且常量池不会存在相同内容的常量
只要其中有一个是变量,结果就在堆中
如果拼接的结果调用intern方法(),返回值就在常量池中
@Test
public void test2(){
String s1="hello";
String s2="world";
String s3="hello"+"world";
String s4=s1+"world";
String s5=s1+s2;
String s6=(s1+s2).intern();
System.out.println(s3 == s4);//false
System.out.println(s3 == s5);//false
System.out.println(s4 == s5);//false
System.out.println(s3 == s6);//true
}
一道面试题
public class FaceTest {
String str=new String("good");
char[]ch={'t','e','s','t'};
public void change(String str, char[] ch){
str="test ok";
ch[0]='b';
}
public static void main(String[] args) {
FaceTest ft=new FaceTest();
ft.change(ft.str,ft.ch);
System.out.println(ft.str);//good
System.out.println(ft.ch);//best
}
堆heap
三部分 新生区 养老区 永久区(方法区 元空间)
字符串常用方法
int length():返回此字符串的长度。
* char charAt(int index):返回指定索引处的 char 值
* boolean isEmpty():当且仅当 length() 为 0 时返回 true。
* String toLowerCase():使用默认语言环境的规则将此 String 中的所有字符都转换为小写。
* String toUpperCase():使用默认语言环境的规则将此 String 中的所有字符都转换为大写。
* String trim():返回字符串的副本,忽略前导空白和尾部空白。
* boolean equals(Object anObject) :将此字符串与指定的对象比较。
boolean equalsIgnoreCase(String anotherString) :将此 String 与另一个 String 比较,不考虑大小写。
String concat(String str) :将指定字符串连接到此字符串的结尾。
* int compareTo(String anotherString) :按字典顺序比较两个字符串。
- String substring(int beginIndex) :返回一个新的字符串,它是此字符串的一个子字符串。
String substring(int beginIndex, int endIndex):返回一个新字符串,它是此字符串的一个子字符串。
@Test
public void test1(){
String s1="Hello world";
System.out.println(s1.length());
System.out.println(s1.charAt(0));
System.out.println(s1.charAt(9));
System.out.println(s1.isEmpty());
System.out.println(s1.toLowerCase());
System.out.println(s1);//s1不可变的
System.out.println(s1.toUpperCase());
String s3=" hello world ";
System.out.println(s3.trim());
String s4="hello world";
System.out.println(s1.equals(s4));
System.out.println(s1.equalsIgnoreCase(s4));
String s6="abc";
String s7="abd";
System.out.println(s6.compareTo(s7));
}
boolean endsWith(String suffix) :测试此字符串是否以指定的后缀结束。
boolean startsWith(String prefix) :测试此字符串是否以指定的前缀开始。
boolean startsWith(String prefix, int toffset) :测试此字符串从指定索引开始的子字符串是否以指定前缀开始。
boolean contains(CharSequence s) :当且仅当此字符串包含指定的 char 值序列时,返回 true。
int indexOf(String str) : 返回指定子字符串在此字符串中第一次出现处的索引。
int indexOf(String str, int fromIndex) :返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。
int lastIndexOf(String str) :返回指定子字符串在此字符串中最右边出现处的索引。
int lastIndexOf(String str, int fromIndex) : 返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索。
public void test2(){
String s1="helloworld";
System.out.println(s1.startsWith("He"));
System.out.println(s1.startsWith("he",1));
System.out.println(s1.endsWith("d"));
System.out.println(s1.contains("abc"));
System.out.println(s1.indexOf("e"));
System.out.println(s1.indexOf("e",2));
System.out.println(s1.lastIndexOf("l"));
System.out.println(s1.lastIndexOf("l", 5));
}
如何使lastIndexOf和indexOf索引值一致?
要么该字符只在字符串中出现一次,要么不在字符串中。
涉及到String类与其他结构之间的转换
String与基本数据类型、包装类之间的转换
String—>基本数据类型、包装类:调用包装类的静态方法:parseXxx(str)
基本数据类型、包装类—>String:调用String重载valueOf(xxx)
@Test
public void test(){
String s1="123";
int num=Integer.parseInt(s1);
System.out.println(num);
String s = String.valueOf(num);
System.out.println(s);
String s3=num+"";
System.out.println(s3);
}
String与char[]之间的转换
string–>char[]:调用String的toCharArray()
char[]–>String:调用String的构造器
题目将字符串abc123修改为a21cb3
public void test2(){
String str="abc123";
char[]ch1=str.toCharArray();
for (int i = 0; i <ch1.length ; i++) {
System.out.println(ch1[i]);
}
char temp;
for (int i = 1; i <=(ch1.length-1)/2 ; i++) {
temp=ch1[i];
ch1[i]=ch1[ch1.length-i-1];
ch1[ch1.length-i-1]=temp;
}
for (int i = 0; i <ch1.length ; i++) {
System.out.print(ch1[i]);
}
}
char数组转化为字符串
char[]chs={'h','e','l','l','o'};
String s3=new String(chs);
System.out.println(s3);
String与byte之间的转换
String–>byte[]:调用String的getBytes()
byte[]—>String:调用String的构造器
编码:字符串—字节(看得懂----看不懂的二进制数据)
解码:编码的逆过程:字节—字符串(看不懂的二进制数—看的懂)
@Test
public void test3() throws UnsupportedEncodingException {
// String--->转换为byte[]数组
String str="abc123中国";
byte[]bytes=str.getBytes();
System.out.println(Arrays.toString(bytes));
byte[]gbk=str.getBytes("gbk");
System.out.println(Arrays.toString(gbk));
//byte[]数组转化为String
String str2=new String(bytes);
System.out.println(str2);
String str3=new String(gbk);
System.out.println(str3);
String gbk1 = new String(gbk, "gbk");
System.out.println(gbk1);
}
@Test
public void test4(){
String s1="javaEEhadoop";
String s2="javaEE";
String s3=s2+"hadoop";
System.out.println(s1 == s3);//false
final String s4="javaEE";
String s5=s4+"hadoop";
System.out.println(s1 == s5);//true
}
StringBuffer和StringBuilder的使用
String、StringBuffer、StringBuilder方法的异同?
String:不可边变的字符序列;底层使char[]数组存储
StringBuffer:可变的字符序列;线程安全,效率低;底层使char[]数组存储
StringBuilder:可变的字符序列;jdk5.0新增,线程不安全,效率高;底层使char[]数组存储
源码分析
String str=new String();//char[]value=new char[0];
* String str1=new String(“abc”);//char[]value=new char[]{‘a’,‘b’,‘c’};
* StringBuffer sb1=new StringBuffer();//char[]value =new char[16];底层创建了一个长度是16的数组
* sb1.append(‘a’);//value[0]=‘a’;
* sb1.append(‘b’);//value[1]=‘b’;
* StringBuffer sb2=new StringBuffer(“abc”);//char[]value=new char[“abc.length()”+capacity]
* //问题1.System.out.println(sb2.length);//3
* //问题2.扩容问题:如果要添加的数据底层数组盛不下了,那就需要扩容底层数组。
* 默认情况下,扩容为原来容量的2倍+2,同时将原有数组中的元素复制到新的数组中。
* 指导意义:开发中建议大家使用:StringBuffer(int capacity)或StringBUilder(int capacity)
/*StringBuffer常用方法:
* 增:append()
* 删delete(int start,int end)
* 改:setCharAt(int n,char ch) /replace(int start,int end,String str)
* 查:charAt(int n)
* 插:insert(int offset,xxx)
* 长度:length()
* 遍历:for()+charAt()/+toString*/
@Test
public void test6(){
StringBuffer sb1=new StringBuffer("abc");
sb1.append(1);
sb1.append("1");
System.out.println(sb1);
sb1.delete(0,2);//左闭右开
System.out.println(sb1);
System.out.println(sb1.charAt(1));
sb1.insert(3,"我爱世界");
System.out.println(sb1);
System.out.println(sb1.length());
for (int i = 0; i <sb1.length() ; i++) {
System.out.println(sb1.charAt(i));
}
System.out.println(sb1.toString());
}