java常用类
1.String类
String是声明为final的,不可被继承。
String实现了Serializable接口:表示字符串是支持序列化的。
实现了Comparable接口:表示String可以比较大小。
String内部定义了final char[] value用于存储字符串数据。String:代表不可变的字符序列。简称:不可变性
public class StringTest {
public static void main(String[] args) {
String s1 ="abc";
String s2 ="abc";
// s1 ="hello";
System.out.println(s1== s2);//true
System.out.println(s1);
System.out.println(s2);
}
}
字符串常量池中是不会存储相同内容的字符串的。
- 当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原用的value进行赋值。
- 当对现有的字符串进行连续操作时,也需要重写指定内存区域赋值,不能使用原用的value进行赋值。
- 当调用String的replace()方法修改指定字符或字符串时,也需要重写指定内存区域赋值,不能使用原用的value进行赋值。
string的实例化方式:
方式一:通过字面量定义的方式
方式二:通过new +构造器的方式
public class StringTest {
public static void main(String[] args) {
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
}
}
String s = new String(“abc”); 方式创建对象,在内存中创建了几个对象?
- 两个,一个是堆空间中new结构,另一个是char[]对应的常量池中的数据:“abc”.
String不同拼接对比
public class StringTest {
public static void main(String[] args) {
String s1 = "hello";
String s2 = "world";
String s3 ="helloworld";
String s4 = "hello"+"world";
String s5 =s1+"world";
String s6 = "hello"+s2;
String s7 = s1+s2;
String s8 = s5 .intern();
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(s3 == s8);//true
}
}
常量与常量的拼接结果在常量池。且常量池中不会存在相同内容的常量。
只要其中有一个是变量,结果就在堆中
如果拼接的结果调用intern()方法,返回值就在常量池中
String类的常用方法
int length():返回字符串的长度:return value.length
char charAt(int index):返回某索引处的字符return value[index]
boolean isEmpty():判断是否是空字符串:return value.length == O
String toLowerCase():使用默认语言环境,将String 中的所有字符转换为小写
String toUpperCase():使用默认语言环境,将 String 中的所有字符转换为大写
String trim():返回字符串的副本,忽略前导空白和尾部空白
boolean equals(Object obj):比较字符串的内容是否相同
boolean equalslgnoreCase(String anotherString):与equals方法类似,忽略大小写
String concat(String str):将指定字符串连接到此字符串的结尾。等价于用“+”
int compareTo(String anotherString):比较两个字符串的大小
String substring(int beginIndex):返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。
String substring(int beginIndex, int endIndex):返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。
public class StringTest {
public static void main(String[] args) {
String str ="HelloWorld";
String str2 ="helloworld";
System.out.println(str.length());//返回字符串长度
System.out.println(str.charAt(0));//返回某索引处的字符
System.out.println(str.isEmpty());//判断字符串是否为空
System.out.println(str.toLowerCase());//转化为小写
System.out.println(str.toUpperCase());//转化为大写
System.out.println(str.equals(str2));//比较字符串内容是否相等
System.out.println(str.equalsIgnoreCase(str2));//忽略大小写,与equals相似
String s1 = " hello world ";
String s2 = s1.trim();//忽略前导和后面部空白
System.out.println("-----"+s1+"-----");//----- hello world -----
System.out.println("-----"+s2+"-----");//-----hello world-----
String s3 ="abc";
String s4 ="abd";
System.out.println(s3.compareTo(s4)); //比较字符串大小
返回一个字符串,该字符串是此字符串的子字符串。 子字符串以指定索引处的字符开头,并扩展到该字符串的末尾。
System.out.println(str.substring(2));//lloWorld
//返回一个字符串,该字符串是此字符串的子字符串。 子串开始于指定beginIndex并延伸到字符索引endIndex - 1 。 因此,子串的长度为endIndex-beginIndex 。
System.out.println(str.substring(2,6));//lloW
}
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 sts, int fromIndex):返回指定子字符串在此字符串中第次出现处的索引、从指定的索引开始
int lastlndexOf(String str):返回指定子字符串在此宁符串中最右边出现处的索引
int lastlndexOf(string str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索
//indexOf和lastlndexOf方法如果未找到都是返回-1
public class StringTest {
public static void main(String[] args) {
String str ="HelloWorld";
System.out.println(str.endsWith("World"));//true
System.out.println(str.startsWith("Hello"));//true
System.out.println(str.startsWith("Hello",0));//true
String str2 = "ll";
System.out.println(str.contains(str2));//true
System.out.println(str.indexOf("ll"));//2
System.out.println(str.indexOf("ll", 4));//-1
System.out.println(str.lastIndexOf("W"));//5
}
}
String replace(char oldChar, char newChar):返回一个新的字符串,它是通过用newChar替换此字符串中出现的所有oldChar得到的。
String replace(CharSequence target,CharSequence replacement):使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
String replaceAll(String regex,String replacement):使用给定的“replacement替换此字符串所有匹配给定的正则表达式的子字符串。
String replaceFirst(String regex,String replacement):使用给定的replacement替换此字符串匹配给定的正则表达式的第一个子字符串。
boolean matches(String regex):告知此字符串是否匹配给定的正则表达式。
String[] split(String regex):根据给定正则表达式的匹配拆分此字符串。
String[] split(String regex,int limit):根据匹配给定的正则表达式来拆分此字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中。
String类的转换
基本数据类型/包装类 ——>String
public class WrapperTest {
public static void main(String[] args) {
// 基本数据类型/包装类 ——>String String.valueOf();
int num =10;
Integer integer = new Integer(num);
String s1 = String.valueOf(num);
String s2 = String.valueOf(integer);
System.out.println(s1);
System.out.println(s2);
}
}
String ——>基本数据类型/包装类
public class WrapperTest {
public static void main(String[] args) {
// String ——>基本数据类型/包装类 调用包装类的parseInt();
String str = "123";
int in1 = Integer.parseInt(str);
String str2 = "true";
boolean b1 = Boolean.parseBoolean(str2);
System.out.println(in1);
System.out.println(b1);
}
}
String --> char[]
public class StringTest {
public static void main(String[] args) {
String str ="HelloWorld";
char[] chars = str.toCharArray();//String --> char[],调用String 的toCharArray()
for (int i = 0; i < chars.length; i++) {
System.out.println(chars[i]);
}
}
}
char[] --> String
public class StringTest {
public static void main(String[] args) {
char[] ch = new char[]{'h','e','l','l','o'};
String s = new String(ch);//char[] --> String:调用String的构造器
System.out.println(s);
}
}
编码:String --> byte[]
public class StringTest {
public static void main(String[] args) throws UnsupportedEncodingException {
String str = "hello中国";
//String --> byte[]:调用String的getBytes()
byte[] bytes = str.getBytes();//使用默认的字符集 utf-8
System.out.println(Arrays.toString(bytes));
byte[] bytes2 = str.getBytes("gbk");
System.out.println(Arrays.toString(bytes2));
}
}
解码:byte[] --> String
public class StringTest {
public static void main(String[] args) throws UnsupportedEncodingException {
String str = "hello中国";
// byte[] --> String 调用String的构造器
byte[] bytes = str.getBytes();
String s = new String(bytes);
System.out.println(s);
}
}
解码时,要求解码使用的字符集必须与编码时使用的字符集一致,否则会出现乱码。
2.StringBuffer和StringBuilder
String、StringBuffer和StringBuilder三者的异同
相同点:底层都是使用char[]存储。
不同点:
1. String;不可变的字符序列,
2. StringBuffer :可变的字符序列,线程安全,效率低,
3. StringBuilder:可变的字符序列,线程不安全,效率高,
//源码分析
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的数组。
public StringBuffer() {
super(16);
}
StringBuffer sb2 = new StringBuffer("abc");//char[] value = new char["abc".length()+16]
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
扩容问题;如果要添加的数组底层数组盛不下,那就需要扩容底层的数组。
默认情况下,扩容为原来容量的2倍+2,同时将原有数组中的元素复制到新的数组中
小提示:
IDEA看源码快捷键 如何返回上一步
Ctrl+Alt+小键盘← 和 Ctrl+Alt+小键盘→
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}
private int newCapacity(int minCapacity) {
// overflow-conscious code
int newCapacity = (value.length << 1) + 2;
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}
StringBuffer类的常用方法
StringBuffer append(xxx):提供了很多的append()方法,用于进行字符串拼接
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)
public int length()
public char charAt(int n )
public void setcharAt(int n ,char ch)
public class StringTest {
public static void main(String[] args) {
StringBuffer str = new StringBuffer("abc");
str.append(1);
str.append('a');
System.out.println(str);//abc1a
System.out.println(str.delete(0, 1));//bc1a
System.out.println(str.replace(0, 1, "hello"));//helloc1a
System.out.println(str.insert(5, 2));//hello2c1a
str.reverse();//反转
System.out.println(str);//a1c2olleh
}
}
3.日期时间
java.lang.System类
System类提供的public static long currentTimeMillis()用来返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差。
此方法适于计算时间差。
public class DateTest {
public static void main(String[] args) {
long start = System.currentTimeMillis();
// 返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差
System.out.println(start);//1663073711257 称为时间戳
}
}
Date类
java.util.Date类(父类)
|—java.sql.Date(子类)
java.sql.Date对应着数据库中的日期类型的变量
public class DateTimeTest {
@Test
public void test1(){
//构造器一;Date():创建一个对应当前时间的Date对象。
Date date1 = new Date();
System.out.println(date1.toString());//Tue Nov 02 21:34:29 CST 2021
System.out.println(date1.getTime()); //1635860069969
//tostring();显示当前的年、月、日、时、分、秒
//getTime():获取当前Data对象对应的毫秒数。
//构造器二:创建指定毫秒数的Dare对象
Date date2 = new Date(1635860069969L);
System.out.println(date2.toString());
//创建java.sql.Date对象
java.sql.Date date3 = new java.sql.Date(35235325345L);
System.out.println(date3);//1971-02-13
}
}
如何将java.util.Date对象转换为java.sql.Date对象?
public class DateTest {
public static void main(String[] args) {
//情况一
// Date date4 = new java.sql.Date(125312324515L);
// java.sql.Date Date5 = (java.sql.Date)date4;
//情况二
Date date6 = new Date();
java.sql.Date date7 = new java.sql.Date(date6.getTime());
System.out.println(date7);
}
}
SimpleDateFormat
SimpleDateFormat的使用:SimpleDateFormat对日期Date类的格式化和解析
- 格式化:日期 —> 字符串
- 解析: 字符串—> 日期
public class SimpleDateFormatTest {
public static void main(String[] args) throws ParseException {
//实例化
SimpleDateFormat simpleDateFormat = new SimpleDateFormat();
//格式化:日期 ---> 字符串
Date date = new Date();
String format = simpleDateFormat.format(date);
System.out.println(format);//22-9-13 下午9:23
//解析: 字符串---> 日期
String str = "21-11-4 下午7:15";
Date parse = simpleDateFormat.parse(str);
System.out.println(parse);//Thu Nov 04 19:15:00 CST 2021
System.out.println("----------一般使用自己指定的格式------------");
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date date2 = new Date();
System.out.println(dateFormat.format(date2));//2022-09-13 09:25:47
}
}
Calender日历类
Calendar是一个抽象基类,主用用于完成日期字段之间相互操作的功能。
public class CalendarTest {
public static void main(String[] args) throws ParseException {
//如何实例化?
//方式一:创建其子类(GregorianCalendar)的对象
//方式二:调用其静态方法getInstance()
Calendar instance = Calendar.getInstance();
System.out.println(instance.getClass());//class java.util.GregorianCalendar
//常用方法
//get()
System.out.println(instance.get(Calendar.DAY_OF_MONTH));//13
System.out.println(instance.get(Calendar.YEAR));//2022
//set()
instance.set(Calendar.DAY_OF_MONTH,20);
System.out.println(instance.get(Calendar.DAY_OF_MONTH));//20
//add()
instance.add(Calendar.DAY_OF_MONTH,3);
System.out.println(instance.get(Calendar.DAY_OF_MONTH));//23
//getTime() 日历类--->Date
System.out.println(instance.getTime());
//setTime() //Date--->日历类
Date date1 = new Date();
instance.setTime(date1);
int day = instance.get(Calendar.DAY_OF_MONTH);
System.out.println(day);
}
}
- 获取月份时:一月是0,二月是1,以此类推,12月是11
- 获取星期时:周日是1,周一是2,。。。周六是7
这些API面临着一些问题:
1. 可变性:像日期和时间这样的类应该是不可变的。
2. 偏移性:Date中的年份是从1900开始的,而月份都从O开始。
3. 格式化:格式化只对Date有用,Calendar则不行。
4. 此外,它们也不是线程安全的;
接下来,让我们看看jdk8中新日期时间API
LocalDate、LocalTime、LocalDateTime
public class TimeTest {
public static void main(String[] args) {
//now():获取当前的日期、时间、日期+时间 ,LocalDateTime的使用频率较高
LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.now();
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDate);//2022-09-14
System.out.println(localTime);//08:37:58.953
System.out.println(localDateTime);//2022-09-14T08:37:58.953
//of():设置指定的时间。无偏移量
LocalDateTime localDateTime1 = LocalDateTime.of(2021,11,4,21,24,25);
System.out.println(localDateTime1);//2021-11-04T21:24:25
//getXxx:获取
System.out.println(localDateTime.getDayOfWeek());//WEDNESDAY
System.out.println(localDateTime.getDayOfMonth());//14
System.out.println(localDateTime.getDayOfYear());//257
//withXxx:设置 体现了不可变性
LocalDateTime localDateTime2 = localDateTime.withMonth(5);
System.out.println(localDateTime);//2022-09-14T08:46:24.637
System.out.println(localDateTime2);//22022-05-14T08:46:24.637
//plusXxx:添加
LocalDateTime localDateTime3 = localDateTime.plusDays(2);
System.out.println(localDateTime3);//2022-09-16T08:46:24.637
//minusXxx:减去
LocalDateTime localDateTime4 = localDateTime.minusDays(2);
System.out.println(localDateTime4);//2022-09-12T08:46:24.637
}
}
instant 瞬时
public class TimeTest {
public static void main(String[] args) {
//now():获取本初子午线对应的标准时间
Instant instant = Instant.now();
System.out.println(instant);//2021-11-04T13:57:05.455Z
//atOffset 添加时间的偏移量
OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));
System.out.println(offsetDateTime);//2021-11-04T21:57:05.455+08:00
//toEpochMilli():获取自1970年1月1日0时0分0秒开始的毫秒数
long milli = instant.toEpochMilli();
System.out.println(milli);
//通过毫秒数 返回instant的实例
Instant instant1 = Instant.ofEpochMilli(1663116650259L);
System.out.println(instant1);
}
}
DateTimeFormatter
DateTimeFormatter:格式化或解析日期、时间类似于SimpleDateFormat
实例化方式:
1. 预定义的标准格式。如: ISo_LOCAL_DATE_TINE; ISo_LOCAL_DATE; ISo_LOCAL_TIME
2. 本地化相关的祖式。如: ofLocalizedDateTime(Formatstyle.LONG)
3. 自定义的格式。如: ofPattern("yyyy-MM-dd hh : mm : ss E")
4.java比较器
Java中的对象,正常情况下,只能进行比较: ==或!=。不能使用> 或< , 但是在开发场景中,我们需要对多个对象进行排序,言外之意,就需要比较对象的大小。
如何实现?
使用两个接口中的任何一个Comparable 或Comparator
Comparable自然排序
像String、包装类等实现了Comparable接口,重写了compareTo()方法,给出了比较两个对象大小的方式
public class ComparaTest {
public static void main(String[] args) {
String[] arr = new String[]{"aa","bb","gg","ff","cc"};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));//[aa, bb, cc, ff, gg]
}
}
对于自定义类来说,如果需要排序,我们可以让自定类实现Comparable接口,重写compareTo方法。
重写compareTo(obj)的规则:
- 如果当前对象this大于形参对象obj,则返回正整数,
- 如果当前对象this小于形参对象obj,则返回负整数,
- 如果当前对象this等于形参对象obj,则返回零。
public class Goods implements Comparable{
private String name;
private int price;
public Goods(){
}
public Goods(String name, int price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public String toString() {
return "Goods{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
@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("输入的数据类性不一致");
}
}
public void test2(){
Goods[] arr = new Goods[4];
arr[0] = new Goods("xiaomi",20);
arr[1] = new Goods("huawei",30);
arr[2] = new Goods("fppo",15);
arr[3] = new Goods("oppo",15);
Arrays.sort(arr);
//java.lang.ClassCastException: com.afojp.Goods cannot be cast to java.lang.Comparable
//对于自定义类来说,如果需要排序,我们可以让自定类实现Comparable接口,重写compareTo方法。
System.out.println(Arrays.toString(arr));
}
comparator 定制排序
当元素的类型没有实现java.Lang.Comparable接口而又不方便修改代码,或者实现了java.Lang.Comparable接口的排序规则不适合当前的操作,那么可以考虑使用Comparator的对象来排序
重写compare(object o1, object o2)方法,比较o1和o2的大小:
- 如果方法返回正整数,则表示o1大于o2 ;
- 如果返回0,表示相等;
- 返回负整数,表示o1小于o2。
public void test3(){
String[] arr = new String[]{"AA","HH","CC","FF","EE","DD"};
Arrays.sort(arr, new Comparator<String>() {
//按照字符串从大到小排序
@Override
public int compare(String o1, String o2) {
if(o1 instanceof String && o2 instanceof String){
String s1 = (String)o1;
String s2 = (String)o2;
return -s1.compareTo(s2);
}
throw new RuntimeException("数据异常");
}
});
System.out.println(Arrays.toString(arr));
}
Comparable接口与Comparator的使用的对比:
- Comparable接口的方式一旦确定,保证Comparable接口实现类的对象在任何位置都可以比较大小
- Comparator接口属于临时性的比较。
5.System类
System类代表系统,系统级的很多属性和控制方法都放置在该类的内部。该类位于java.lang包。
由于该类的构造器是private的,所以无法创建该类的对象,也就是无法实例化该类。其内部的成员变量和成员方法都是static的,所以也可以很方便的进行调用。
public class Test {
public static void main(String[] args) {
String javaVersion = System.getProperty("java.version");
System.out.println( "java的version: " + javaVersion);
String javaHome = System.getProperty( "java.home");
System.out.println( "java的home : " + javaHome) ;
String osName = System.getProperty( "os.name " );
System. out.println("os的name:" + osName);
String osVersion = System.getProperty( "os.version");
System.out.println( "os的version: " +osVersion) ;
String userName = System.getProperty( "user.name" );
System.out.println( "user的name: " + userName) ;
String userHome = System.getProperty( "user.home" );
System.out.println( "user的home : " + userHome) ;
String userDir = System.getProperty( "user.dir" );
System.out.println( "user的dir: " + userDir);
}
}