2021-5-19
1.字符串
String:字符串,使用一对 “” 括起来
- String声明为final的,不可被继承
- String实现了Serializable接口,表示字符串是支持序列化的
- 实现了Comparable接口,表示String可以比较大小
- String内部定义了final char[] value用于存储字符串数据
- String代表不可变的字符序列。简称:不可变性
- 当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值
- 当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值
- 当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值
- 通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中
- 字符串常量池中是不会存储相同内容的字符串的
- String的实例化方式
- 字面量定义的方式:String s1 = “JavaEE”;
- new + 构造器的方式:String s2 = new String(“JavaEE”);
String s1 = "JavaEE";
String s2 = "JavaEE";
String s3 = new String("JavaEE");
String s4 = new String("JavaEE");
System.out.println(s1 == s2);//true
System.out.println(s1 == s3);//false
System.out.println(s1 == s4);//false
System.out.println(s3 == s4);//false
Person p1 = new Person("Tom",12);
Person p2 = new Person("Tom",12);
System.out.println(p1.name.equals(p2.name));//true
System.out.println(p1.name == p2.name);//true
p1.name = "Jerry";
System.out.println(p2.name);//Tom
-
面试题:String s = String(“abc”);方式创建对象,在内存中创建了几个对象?
-如果字符串常量池中没有"abc"存在,则在字符串常量池中创建一个"abc",同时在堆空间中创建一个 s;如果字符串常量池中已经存在 “abc” 了,则只在堆空间中创建一个 s -
字符串的拼接
- 常量与常量拼接,结果存在常量池中
- 只要与变量拼接,结果就存在堆中
- 如果拼接的结果调用intern()方法,返回值就在常量池中
@Test
public void test{
String s1 = "javaEE";
String s2 = "hadoop";
String s3 = "javaEEhadoop";
String s4 = "javaEE" + "hadoop";
String s5 = s1 + "hadoop";
String s6 = "javaEE" + s2;
String s7 = s1 + s2;
System.out.println(s3 == s4);//true
System.out.println(s3 == s5);//false
System.out.println(s3 == s6);//false
System.out.println(s3 == s7);//false
System.out.println(s5 == s6);//false
System.out.println(s5 == s7);//false
System.out.println(s6 == s7);//false
final String s8 = "javaEE";
String s9 = s8 + "hadoop";
System.out.println(s3 == s9);//true
}
- 一道面试题
public class StringTest{
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(Sstring[] args){
StringTest ex = new StringTest;
ex.change(ex.str,ex.ch);
System.out.println(ex.str);//good
System.out.println(ex.ch);//best
}
}
- JVM中 字符串常量池在在方法区中
- String的常用方法–记
- int length(): 返回字符串的长度 return value.length
- char charAt(int index): 返回某索引处的字符 return value[index]
- boolean isEmpty(): 判断是否是空字符串 return value.length == 0
- String toLowerCase(): 使用默认语言环境,将String中的所有字符转换为小写
- String toUpperCase(): 使用默认语言环境,将String中的所有字符转换为大写
- String trim(): 返回字符串的副本,忽略前导空白尾部空白
- boolean equals(Object obj):比较字符串的内容是否相同
- boolean equalsIgnoreCase(String anotherString): 忽略大小写比较字符串的内容是否相同
- String concat(String str): 将指定字符串连接到该字符串的结尾。等价于用 +
- int compareTo(String anotherString): 比较两个字符串的大小
- String subString(int beginIndex): 返回一个新的字符串 从beginIndex开始截取到结尾
- String subString(int beginIndex,int endIndex): 返回一个新的字符串,从beginIndex开始截取到endIndex结束。左闭右开
- boolean endWith(String suffix): 返回此字符串是否以指定字符串结束
- boolean startWith(String prefix): 返回此字符串是否以指定字符串开始
- boolean startWith(String prefix, int toffset): 返回此字符串从指定索引开始的字符串是否以指定字符串开始
- boolean contains(CharSequende s): 判断此字符串是否包含指定的字符序列
- int indexOf(String str): 返回指定字符串在此字符串中第一次出现处的索引
- int indexOf(String str, int fromIndex): 返回指定字符串在此字符串中,从fromIndex索引往后第一次出现处的索引
- int lastIndexOf(String str): 返回指定字符串在此字符串中,从后往前第一次出现处的索引
- int lastIndexOf(String str, int formIndex): 返回指定字符串在此字符串中,从fromIndex往前第一次出现处的索引
- indeOf()和lastIndexOf()如果没找到返回值都是-1
- String replace(char oldChar, char newChar): 返回一个字符串,使用newChar替换所有的oldChar
- String replace(CharSequence target, CharSequence replacement): 返回一个字符串,使用replacement替换所有的target
- String replaceAll(String regex, String replacement):
- String replaceFirst(String regex, String replacement):
- boolean matches(String regex, String replacement):
- String[] split(String regex):
- String[] split(String regex, int limit):
- String与其他结构之间的转换
- 与基本数据类型和包装类之间的转换
String s = "123";
int x = Integer.parseInt(s);
//将基本数据类型转换为String
String s1 = String.valueOf(x);//或者String s1 = x +"";
- 与char[]之间的转换
String s = "abc123"; //题目:将 "abc123"转换为 "a21cb3"
char[] charArray = s.toCharArray();
char[] arr = new char[]{'h','e','l','l','o'};
String s1 = new String(arr);
- 与byte[]之间的转换
String s = "abc123";
byte[] bytes = s.getBytes();
System.out.println(Arrays.toString(bytes));//[97,98,99,49,50,51]
String s1 = "abc123中国";
byte[] bytes1 = s1.getBytes();//使用默认的字符编码集
System.out.println(Arrays.toString(bytes));//[97,98,99,49,50,51,-28,-72,-83,-27,-101,-67]
byte[] bytes2 = s1.getBytes("gbk");//指定使用gbk编码集
String str1 = new String(bytes1);//使用默认的字符编码集进行编码 "abc123中国"
String str2 = new String(bytes2);//使用默认的字符编码集进行编码 乱码
String str3 = new String(bytes2,"gbk");//使用指定的的字符编码集进行解码 "abc123中国"
- String、StringBuffer、StringBuilder
- String是不可变的字符序列;底层使用char[]存储
- StringBuffer是可变的字符序列;底层使用char[]存储,线程安全的,效率低
- StringBuilder是可变的字符序列;底层使用char[]存储,线程不安全的,效率高。(jdk5.0新增的)
- 源码分析:
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的char数组
sb1.append('a'); //value[0] = 'a';
sb1.append('b'); //value[1] = 'b';
StringBuffer sb2 = new StringBuffer("abc");//char[] value = new char["abc".length + 16];
//StringBuffer和StringBuilder的扩容问题:
//如果append的数据底层数组盛不下了,就需要扩容底层数组,默认情况下扩容为原来容量的2倍+2
//同时将原有数组中的元素复制到新的数组中
//开发中建议用StringBuffer(int capacity)或StringBuilder(int capacity) 避免数组长度不够频繁扩容导致效率降低
//StringBuffer sb = new //StringBuffer(26);//构造一个不带字符,但具有指定初始容量的字符串缓冲区。
//这里定义的是一个26个字符长度的字符缓冲区(默认是16个字符长度);
//与可变长度数组不同的是,这个构造方法会根据字符的长度动态的改变,不会一次//性的增加定义的缓冲区的长度。
- StringBuffer类的常用方法
- StringBuffer append(xxx): 提供了很多重载的方法,对字符串进行拼接 增
- StringBuffer delete(int start,int end): 删除指定位置的内容 删
- StringBuffer replace(int start,int end,String str): 把[start,end)位置替换为str 改
- StringBuffer insert(int offset,xxx):在指定位置插入xxx 插
- StringBuffer reverse(): 把当前字符串序列逆转 改
- public int indexOf(String str) 查
- public String substring(int start,int end): 返回 [start,end)位置的子字符串查
- public int length()长度
- public char charAt(int n)查
- public void setCharAt(int n,char ch)改
- 总结:增、删、改、查、插、长度、遍历
- 三者的效率:StringBuilder > StringBuffer > String
2.日期和时间
- JDK8之前的日期和时间的API
- System类中的currentTimeMillis()方法
long time = System.currentTimeMillis();//返回1970年1月1日0时0分0秒到现在的ms数
- java.util.Date
- 两个构造器的使用
- 两个方法的使用
Date date1 = new Date();//创建一个对应当前时间的Date对象
System.out.println(date1.toString());// sat Feb 16 16:35:31 GMT+08:00 2019
System.out.println(date1.getTime());//155506341926 返回date1对象对应时间距离1970年的ms数
Date date2 = new Date(155506341926);//创建一个指定时间的Date对象
System.out.println(date2.toString());// sat Feb 16 16:35:31 GMT+08:00 2e19
- java.sql.Date :数据库中的Date类型
java.sql.Date date3 = new java.sql.Date(155506341926);
System.out.println(date3);// 2019-02-16
如何把java.util.Date类的对象转换为java.sql.Date类的对象
Date date4 = new Date();
java.sql.Date date5 = new java.sql.Date(date5.getTime());//妙啊
- SimpleDateFormat : 对Date类的格式化和解析
- 格式化:日期–>字符串
- 解析:格式化的逆过程
SimpleDateFormat sdf = new SimpleDateFormat(yyyy-MM-dd hh:mm:ss);
//格式化
String format = sdf.format(new Date());
System.out.println(format);//2021-05-16 21:56:12
Date date = sdf.parse("2021-05-16 21:56:12");//这里的字符串必须符合SimpleDateFormat构造器里的格式
System.out.println(date);
- 练习题:将字符串 "2021-05-16"转换为 java.sql.Date
String str = "2021-05-16";
SimpleDateFormat sdf = new SimpleDateFormat(yyyy-MM-dd);
Date date = sdf.parse("2021-05-16");
java.sql.Date sdate = new java.sql.Dat(date.getTime());
System.out.println(sdate);
- java.util.Calender
1.实例化
//方式一:Calender是一个抽象类,可以创建其子类(GregorianCalender)的对象
//方式二:调用Calender的静态方法getInstance()
Calender calender = Calender.getInstance();
2.常用方法
//get()
int days = calender.get(Calender.DAY_OF_MONTH);
System.out.println(days);
System.out.println(calender.get(Calender.DAY_OF_YEAR));
//set()
calender.set(Calender.DAY_OF_MONTH,22);
days = calender.get(Calender.DAY_OF_MONTH);
System.out.println(days);
//add()
calender.add(Calender.DAY_OF_MONTH,3);
days = calender.get(Calender.DAY_OF_MONTH);
System.out.println(days);
calender.add(Calender.DAY_OF_MONTH,-3);
days = calender.get(Calender.DAY_OF_MONTH);
System.out.println(days);
//getTime():日历类-->Date
Date date = calender.getTime();
System.out.println(date);
//setTime():Date-->日历类日
Date date1 = new Date();
calender.setTime(date1);
- JDK8中的日期时间API
- JDK1.0中的Date和JDK1.1中的Calender不好用!
- Calender出来之后Date很多方法都弃用了,但是Calender没比Date好多少
- 可变性:像日期和时间这样的类应该是不可变的
- 偏移性:Date中的年份是从1900开始的,而月份都是从0开始的
- 格式化只对Date有用,而Calender则不行、
- 线程不安全,不能处理闰秒等
- JDK8中吸收Joda-Time的精华,引入java.time
- LocalDate、LocalTime、LocalDateTime
public void test{
//now(): 获取当前的日期、时间、日期+时间
LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.now();
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDate);
System.out.ptintln(localTime);
System.out.ptintln(localDateTime);
//of():设置指定时间的对象
LocalDateTime localDateTime1 = LocalDateTime().of(2020,10,6,13,23,43);
System.out.ptintln(localDateTime1);
//getXxx() 获取
System.out.println(localDateTime.getDayOfMonth());
System.out.println(localDateTime.getDayOfWeek());
System.out.println(localDateTime.getMonth());
System.out.println(localDateTime.getMonthValue());
System.out.println(localDateTime.getMinute());
//withXxx() 设置, 体现了不可变性
LocalDate localDate1 = localDate.withDayOfMonth(22);
System.out.println(localDate); 2021-05-17
System.out.println(localDate1); 2021-05-22
LocalDateTime localDateTime2 = LocalDateTime.withHour(4);
System.out.ptintln(localDateTime);
System.out.ptintln(localDateTime2);
//plusXxx()
LocalDateTime localDateTime3 = localDateTime.plusMonths(3);
System.out.ptintln(localDateTime);
System.out.ptintln(localDateTime3);
//minusXxx()
LocalDateTime localDateTime4 = localDateTime.minusMonths(-3);
System.out.ptintln(localDateTime);
System.out.ptintln(localDateTime4);
- Instant 类似于java.util.Date类
@Test
public void test(){
//now 获取本初子午线对应的标准时间
Instant instant = Instant.now();
System.out.println(instant);
//添加时间的偏移量
OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));
System.out.println(offsetDateTime);
//toEpochMilli():获取自1970年1月1日0分0秒(UTC)开始的毫秒数 -->Date类的getTime()方法
long milli = instant.toEpochMilli(); -->getTime()
System.out.println(milli);
//ofEpochMilli():通过给定的毫秒数,获取Instant实例 -->Date(long millis)
Instant instant1 = Instant.ofEpochMilli(1550475314878L);
System.out.println(instant1);
}
- DateTimeFormatter //格式化与解析日期与时间 -->类似于SimpleDateFormat
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss);
//格式化
String str = dateTimeFormatter.format(LocalDateTime.now());
//解析
TemporalAccessor accessor = dateTimeFormatter.parse(2021-05-20 07:00:00);
System.out.println(accessor);
- 还有很多关于时间的类和方法要学会看API活学活用,自学自用~
3.Java比较器
- Java中常涉及到对象数组的排序问题,那么就涉及到对象之间的比较问题。
- 自然排序:java.lang.Comparable
- 定制排序:java.util.Comparator
- 自然排序,Comparable接口的使用
//1.像String、包装类等实现了Comparable接口、重写了compareTo(obj)方法,给出了比较两个对象大小的方式
//2.像String、包装类重写了compareTO()方法以后,进行了从小到大的排序
//3.重写CompareTo(obj)方法的规则
//如果当前对象this > 形参对象obj ,返回正整数
//如果当前对象this < 形参对象obj ,返回负整数
//如果当前对象this = 形参对象obj ,返回0
//4.对于自定义类来说,如果需要排序,我们可以让自定义类实现Comparable接口,重写compareTo()方法,在compareTo(obj)方法中指明如何排序
@Override
public int compareTo(Object o){
if(o instanceof Goods){
Goods goods = (Goods)o;
if(this.price > goods.price){
return 1;
}else if(this.price < goods.price){
return -1;
}else{
//return 0;
return this.name.compareTo(goods.name);
}
//方式二: return Double.compare(this.price,goods.price);
}
throw new RuntimeException("传入的数据类型不一致");
}
- 定制排序,java.util.Comparator
//当元素的类型没有实现java.lang.Comparable接口而又不太方便修改代码
//或者实现了java.lang.Comparable接口的排序规则不适合当前的操作
//那么可以考虑使用Cmparator的对象来排序
//重写compare(Object o1,Object o2)方法 比较o1,o2的大小
//方法返回正整数,表示o1 > o2
//方法返回负整数,表示o1 < o2
//方法返回0,表示o1 = o2
@Test
public void test{
String[] arr = new String[]{"AA","BB","CC","DD","EE","FF"};
Arrays.sort(arr,new Comparator(){
//按照字符串从大到小的顺序排序
@Override
public int compare(Object o1,Object o2){
if(o1 instanceof String && o2 instanceof String){
String s1 = (String)o1;
String s2 = (String)o2;
return -s1.compareTo(s2);
}
//return 0;
throw new RuntimeException("输入的数据类型不一致");
}
})
}
4.其他常用类
1.System类
- System代表系统,系统级的很多属性和控制方法都放置在该类的内部。位于java.lang包下
- 由于该类的构造器是private的,所以无法创建该类的对象,其内部的成员变量和成员方法都是static的所以可以很方便的调用
- 成员变量:包括in、out、err三个成员变量,分别代表标准输入流InpuStream(键盘输入),标准输出流PrintStream(显示器),标准错误输出流PrintStream(显示器)。
- 成员方法:
- native long currentTimeMillis()
- void exit(int status)
- void gc()
- String getProperty(String key)
2.Math类
- java.lang.Math提供了一系列静态方法用于科学计算,其方法的参数和返回值一般为double类型
3.BigInteger
- Integer类作为int的包装类,能存储的最大整型值为231-1,Long类也是有限的,最大为263-1.如果要表示再大的整数,不管是基本数据类型还是包装类都无能为力
- java.math包的BigInteger可以表示不可变的任意精度的整数。BigInteger提供所有java的基本整数操作符的对应物,并提供java.lang.Math的所有相关方法,还提供一些其他运算
- 构造器BigInteger(String val) 根据字符串构建BigInteger对象
4.BigDecimal
- 一般Float和Double类可以用来做科学计算或工程计算,但在商业计算中,要求数字精度比较高,故用到java.Math.BigDecimal类
- BigDecimal支持不可变的任意精度的有符号十进制定点数