Java常用类

字符串相关的类

String特性

基本介绍

String类:代表字符串。Java 程序中的所有字符串字面值(如 “abc” )都作为此类的实例实现。

String是一个final类,代表不可变的字符序列。(同时表示不可被继承)

字符串是常量,用双引号引起来表示。它们的值在创建之后不能更改。

String对象的字符内容是存储在一个字符数组value[]中的。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

由这个JDK源码也可以看出一些基本信息,比如这个类继承了Serializable接口,说明这个类是可以被序列化的。实现了Comparable接口:表示String可以比较大小

定义字符时候JVM内存分配如下:

在这里插入图片描述

可以看出,字符串属于常量,并且每个字符串只能保存一份,比如s1定义为abc,s2自动的指向这个常量,同时如果s1再次赋值,之前的值是不会消失,而是在常量池中创建一个新的数据并将s1指向这个新的地址。

String不可变性的理解

  • 当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值。(在字符串常量池中创建了新的数据)
  • 当对现的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。(原因同上)
  • 当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。(同上)

举个栗子:

String s1 = "abc";//字面量的定义方式
String s2 = "abc";
s1 = "hello";

System.out.println(s1 == s2);//比较s1和s2的地址值,true

System.out.println(s1);//hello
System.out.println(s2);//abc

String s3 = "abc";
s3 += "def";
System.out.println(s3);//abcdef
System.out.println(s2);

String s4 = "abc";
String s5 = s4.replace('a', 'm');
System.out.println(s4);//abc
System.out.println(s5);//mbc

不同的实例化方式

方式一:通过字面量定义的方式

方式二:通过new + 构造器的方式

//通过字面量定义的方式:此时的s1和s2的数据javaEE声明在方法区中的字符串常量池中。
String s1 = "javaEE";
String s2 = "javaEE";
//通过new + 构造器的方式:此时的s3和s4保存的地址值,是数据在堆空间中开辟空间以后对应的地址值。
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(s3 == s4);//false

在这里插入图片描述

[ 解释s3 == s4为false ]:这是因为,String本质上就是一个char数组,而new的时候是在堆中创建这个数据,这个数据不是Static类型,每次新建都会在堆中创建新的数据。

字符串拼接方式赋值的对比

在这里插入图片描述

说明:

  • 常量与常量的拼接结果在常量池。且常量池中不会存在相同内容的常量。
  • 只要其中有一个是变量,结果就在堆中
  • 如果拼接的结果调用intern()方法,返回值就在常量池中

String使用陷阱

  • String s1 = “a”; 说明:在字符串常量池中创建了一个字面量为"a"的字符串。
  • s1 = s1 + “b”; 说明:实际上原来的“a”字符串对象已经丢弃了,现在在堆空间中产生了一个字符串s1+“b”(也就是"ab")。如果多次执行这些改变串内容的操作,会导致大量副本字符串对象存留在内存中,降低效率。如果这样的操作放到循环中,会极大影响程序的性能。
  • String s2 = “ab”; 说明:直接在字符串常量池中创建一个字面量为"ab"的字符串。
  • String s3 = “a” + “b”; 说明:s3指向字符串常量池中已经创建的"ab"的字符串。 String s4 = s1.intern(); 说明:堆空间的s1对象在调用intern()之后,会将常量池中已经存在的"ab"字符串 赋值给s4。

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):与equals方法类似,忽略大小写
String concat(String str):将指定字符串连接到此字符串的结尾。 等价于用“+int compareTo(String anotherString):比较两个字符串的大小
String substring(int beginIndex):返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。
String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。

boolean endsWith(String suffix):测试此字符串是否以指定的后缀结束
boolean startsWith(String prefix):测试此字符串是否以指定的前缀开始
boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的子字符串是否以指定前缀开始

boolean contains(CharSequence s):当且仅当此字符串包含指定的 char 值序列时,返回 true
    
//下面这些方法都是没找到返回-1
int indexOf(String str):返回指定子字符串在此字符串中第一次出现处的索引
int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始
int lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现处的索引
int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索
    
替换字符类方法:
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个,如果超过了,剩下的全部都放到最后一个元素中。

JVM中字符串常量池存放位置说明:

jdk 1.6 (jdk 6.0 ,java 6.0):字符串常量池存储在方法区(永久区)

jdk 1.7:字符串常量池存储在堆空间

jdk 1.8:字符串常量池存储在方法区(元空间)

StringBuffer类

java.lang.StringBuffer代表可变的字符序列,JDK1.0中声明,可以对字符串内容进行增删,此时不会产生新的对象。很多方法与String相同。 作为参数传递时,方法内部可以改变值。

StringBuffer类不同于String,其对象必须使用构造器生成。三个构造器:

  • StringBuffer():初始容量为16的字符串缓冲区
  • StringBuffer(int size):构造指定容量的字符串缓冲区
  • StringBuffer(String str):将内容初始化为指定字符串内容
String s = new String("我喜欢学习");
StringBuffer buffer = new StringBuffer("我喜欢学习");
buffer.append("数学"); 

在这里插入图片描述

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() :把当前字符序列逆转
  • 当append和insert时,如果原来value数组长度不够,可扩容。

  • 如上这些方法支持方法链操作。

例如:

StringBuffer buffer = new StringBuffer();
buffer.append("a")
    .append("b")
    .insert(2,"haha");
//可以直接多层调用方法叫做方法链操作

其他常用方法:

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)	//替换指定位置的字符

StringBuilder类

StringBuilder 和 StringBuffer 非常类似,均代表可变的字符序列,而且提供相关功能的方法也一样

对比String、StringBuffer、StringBuilder

  • String(JDK1.0):不可变字符序列

  • StringBuffer(JDK1.0):可变字符序列、效率低、线程安全

  • StringBuilder(JDK 5.0):可变字符序列、效率高、线程不安全

  • 三者的执行效率从高到低排列:StringBuilder > StringBuffer > String

日期时间API

System类中的currentTimeMillis()

获取系统当前时间,返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差,也称之为时间戳。

long time = System.currentTimeMillis();

此方法适于计算时间差。

java.util.Date类

表示特定的瞬间,精确到毫秒。

构造器:

  • Date():使用无参构造器创建的对象可以获取本地当前时间。

  • Date(long date) :传递一个毫秒值就可以转换成一个日期,例如:

    + System.out.println(new Date(System.currentTimeMillis()));	//Mon Feb 08 13:57:48 CST 2021
    

常用的方法:

  • getTime():返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。

  • toString():把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy 其中: dow 是一周中的某一天 (Sun, Mon, Tue, Wed, Thu, Fri, Sat),zzz是时间标准。

Date date = new Date();
System.out.println(date.getTime());
System.out.println(date.toString());

java.text.SimpleDateFormat类

Date类的API不易于国际化,大部分被废弃了,java.text.SimpleDateFormat 类是一个不与语言环境有关的方式来格式化和解析日期的具体类。

它允许进行格式化:日期 —> 文本、解析:文本 —> 日期

格式化:

  • SimpleDateFormat():默认的模式和语言环境创建对象
  • public SimpleDateFormat(String pattern):该构造方法可以用参数pattern 指定的格式创建一个对象,该对象调用。pattern 可以指定日期解析的格式
  • public String format(Date date):方法格式化时间对象date
public static void main(String[] args) {
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm");
    System.out.println(simpleDateFormat.format(new Date()));
}

解析:

  • public Date parse(String source):从给定字符串的开始解析文本,以生成 一个日期。

本地日期、本地时间、本地日期时间的使用:LocalDate / LocalTime / LocalDateTime

新时间日期API,Java 8 吸收了 Joda-Time 的精华,以一个新的开始为 Java 创建优秀的 API。

LocalDate、LocalTime、LocalDateTime类是其中较重要的几个类,它们的实例是不可变的对象,分别表示使用 ISO-860日历系统的日期、时间、日期和时间。它们提供了简单的本地日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息。

  • LocalDate代表IOS格式(yyyy-MM-dd)的日期,可以存储 生日、纪念日等日期。
  • LocalTime表示一个时间,而不是日期。
  • LocalDateTime是用来表示日期和时间的,这是一个最常用的类之一。
方法描述
now() / * now(ZoneId zone)静态方法,根据当前时间创建对象/指定时区的对象
of()静态方法,根据指定日期/时间创建对象
getDayOfMonth()/getDayOfYear()获得月份天数(1-31) /获得年份天数(1-366)
getDayOfWeek()获得星期几(返回一个 DayOfWeek 枚举值)
getMonth()获得月份, 返回一个 Month 枚举值
getMonthValue() / getYear()获得月份(1-12) /获得年份
getHour()/getMinute()/getSecond()获得当前对象对应的小时、分钟、秒

日期时间格式化类:DateTimeFormatter

格式化或解析日期、时间。类似于SimpleDateFormat

自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)

方 法描 述
ofPattern(String pattern)静态方法 , 返回一个指定字符串格式的 DateTimeFormatter
format(TemporalAccessor t)格式化一个日期、时间,返回字符串
parse(CharSequence text)将指定格式的字符序列解析为一个日期、时间

例如:

// 重点:自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
//格式化
String str = formatter.format(LocalDateTime.now());
System.out.println(str);//2021-02-07 03:52:09

//解析
TemporalAccessor accessor = formatter.parse("2021-02-07 03:52:09");
System.out.println(accessor);

Java比较器

Java中的对象,正常情况下,只能进行比较:== 或 != 。不能使用 > 或 < ,但是在开发场景中,我们需要对多个对象进行排序,言外之意,就需要比较对象的大小。如何实现?使用两个接口中的任何一个:Comparable 或 Comparator

自然排序Comparable

实现 Comparable 的类必须实现 compareTo(Object obj) 方法,两个对象即通过 compareTo(Object obj) 方法的返回值来比较大小。如果当前对象this大于形参对象obj,则返回正整数,如果当前对象this小于形参对象obj,则返回负整数,如果当前对象this等于形参对象obj,则返回零。

实现Comparable接口的对象列表(和数组)可以通过 Collections.sort 或 Arrays.sort进行自动排序。实现此接口的对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。

Comparable 的典型实现:(默认都是从小到大排列的),以下这些类都是实现了这个接口,并且按照一定的规则经行重写:

  • String:按照字符串中字符的Unicode值进行比较
  • Character:按照字符的Unicode值来进行比较
  • 数值类型对应的包装类以及BigInteger、BigDecimal:按照它们对应的数值大小进行比较
  • Boolean:true 对应的包装类实例大于 false 对应的包装类实例
  • Date、Time等:后面的日期时间比前面的日期时间大

对于自定义类来说,如果需要排序,我们可以让自定义类实现Comparable接口,重写compareTo(obj)方法。在compareTo(obj)方法中指明如何排序。例如:

public class TestDate implements Comparable {
    String name;
    int age;

    public TestDate(int age) {
        this.age = age;
    }

    public static void main(String[] args) {
        TestDate date = new TestDate(10);
        TestDate date1= new TestDate(7);
        System.out.println(date.compareTo(date1));  //1
    }

    public int compareTo(Object o) {
        if (o instanceof TestDate){
            //强转
            TestDate date = (TestDate) o;
            if (this.age < date.age){
                return -1;  //表示当前对象比传入对象age小。
            }else if (this.age > date.age){
                return 1;   //比传入对象大
            }
            return 0;   //一样
        }
        throw new RuntimeException("对象类型都特么不一样你比较个毛线");
    }
}

这个时候我们也可以创建这个对象的数组,然后使用Arrays经行排序,排序使用的规则就是这个接口的实现。

public class TestDate implements Comparable {
    String name;
    int age;

    public TestDate(int age) {
        this.age = age;
    }

    public static void main(String[] args) {
        TestDate date[] = new TestDate[4];
        date[0] = new TestDate(10);
        date[1] = new TestDate(2);
        date[2] = new TestDate(55);
        date[3] = new TestDate(30);
        System.out.println(Arrays.toString(date));  //[10, 2, 55, 30]
        Arrays.sort(date);
        System.out.println(Arrays.toString(date));  //[2, 10, 30, 55]
    }

    public int compareTo(Object o) {
        if (o instanceof TestDate){
            //强转
            TestDate date = (TestDate) o;
            if (this.age < date.age){
                return -1;  //表示当前对象比传入对象age小。
            }else if (this.age > date.age){
                return 1;   //比传入对象大
            }
            return 0;   //一样
        }
        throw new RuntimeException("对象类型都特么不一样你比较个毛线");
    }

    @Override
    public String toString() {
        return age+"";
    }
}

定制排序Comparator

当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码,或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,那么可以考虑使用 Comparator 的对象来排序,强行对多个对象进行整体排序的比较。

重写compare(Object o1,Object o2)方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示 o1小于o2。

可以将 Comparator 传递给 sort 方法(如 Collections.sort 或 Arrays.sort), 从而允许在排序顺序上实现精确控制。

还可以使用 Comparator 来控制某些数据结构(如有序 set或有序映射)的顺序,或者为那些没有自然顺序的对象 collection 提供排序。

public class Test2 {
    String name;
    int age;

    public Test2(int age) {
        this.age = age;
    }

    public static void main(String[] args) {
        Test2 date[] = new Test2[4];
        date[0] = new Test2(10);
        date[1] = new Test2(2);
        date[2] = new Test2(55);
        date[3] = new Test2(30);
        System.out.println(Arrays.toString(date));  //[10, 2, 55, 30]
        Arrays.sort(date, new Comparator<Test2>() {
            public int compare(Test2 o1, Test2 o2) {
                if (o1.age < o2.age){
                    return -1;  //表示当前对象比传入对象age小。
                }else if (o1.age > o2.age){
                    return 1;   //比传入对象大
                }
                return 0;   //一样
            }
        });
        System.out.println(Arrays.toString(date));  //[2, 10, 30, 55]
    }
    @Override
    public String toString() {
        return age+"";
    }
}

总的来说,我们可以实现Comparator接口实现对比规则,再使用这个实现类来对比定制的对比对象。或者传递给Arrays。sort()方法来实现排序

System类

System类代表系统,系统级的很多属性和控制方法都放置在该类的内部。该类位于java.lang包。

由于该类的构造器是private的,所以无法创建该类的对象,也就是无法实例化该类。其内部的成员变量和成员方法都是static的,所以也可以很方便的进行调用。

System类内部包含in、out和err三个成员变量,分别代表标准输入流 (键盘输入),标准输出流(显示器)和标准错误输出流(显示器)。

几个常用的方法:

  • native long currentTimeMillis():该方法的作用是返回当前的计算机时间,时间的表达格式为当前计算机时 间和GMT时间(格林威治时间)1970年1月1号0时0分0秒所差的毫秒数。

  • void exit(int status):该方法的作用是退出程序。其中status的值为0代表正常退出,非零代表 异常退出。使用该方法可以在图形界面编程中实现程序的退出功能等。

  • void gc():该方法的作用是请求系统进行垃圾回收。至于系统是否立刻回收,则取决于系统中垃圾回收算法的实现以及系统执行时的情况。

  • String getProperty(String key):该方法的作用是获得系统中属性名为key的属性对应的值。系统中常见的属性名以及属性的作用如下表所示:

在这里插入图片描述

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);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值