常用包
- java.lang包,语言包,基础包,使用时不需要导入
- java.util包,工具包,里面有很多工具类
Object类
- Object类位于java.lang包中,java.lang包 包含着Java最基础和核心的类,在编译时会自动导入;Object类是所有Java类的根基类。
- 如果在类的声明中未使用extends:关键字指明其基类,则默认基类为Object类
public class Person
public class Person extends Object
- 在Object类中提供了一些常用的方法
- JavaAPI帮助文档:
https://www.matools.com/file/manual/jdk_api_1.8_google/index.html?overview-summary.html
Object类方法 - toString
- public String toString()
- 返回对象的字符串表示形式。
- 返回值:包名.类名'@'对象哈希码的无符号的十六进制表示.
getClass().getName() + '@' + Integer.toHexString(hashCode())
//打印对象的时候,默认调用对象的toString()方法
public class ObtoString {
public static void main(String[] args) {
User user = new User();
user.uname = "zhangsan";
System.out.println(user);
System.out.println(user.toString());
User user1 = new User();
System.out.println(user1.toString());
}
}
class User {
public String id;
public String uname;
private String password;
}
输出结果:
commonClasses.User@4554617c
commonClasses.User@4554617c
commonClasses.User@74a14482
//重写toString()方法:
public class ObtoString {
public static void main(String[] args) {
User user = new User();
user.uname = "zhangsan";
System.out.println(user);
System.out.println(user.toString());
User user1 = new User();
System.out.println(user1.toString());
}
}
class User {
public String id;
public String uname;
private String password;
//重写toString方法(尽量自动生成) -> 快捷键 alert + Insert
@Override
public String toString() {
return "User{" +
"id='" + id + '\'' +
", uname='" + uname + '\'' +
'}';
}
}
输出结果:
User{id='null', uname='zhangsan'}
User{id='null', uname='zhangsan'}
User{id='null', uname='null'}
Object类方法 - hashCode
public int hashCode()
- 返回对象的哈希码值。
- hashCode的总合同:
- 只要在执行Java应用程序时多次在同一个对象上调用该方法, hashCode方法必须始终返回相同的整数,前提是修改了对象中equals比较中的信息。 该整数不需要从一个应用程序的执行到相同应用程序的另一个执行保持一致。
- 如果根据equals(Object)方法两个对象相等,则在两个对象中的每个对象上调用hashCode方法必须产生相同的整数结果。
- 不要求如果两个对象根据equals(java.lang.Object)方法不相等,那么在两个对象中的每个对象上调用hashCode方法必须产生不同的整数结果。 但是,程序员应该意识到,为不等对象生成不同的整数结果可能会提高哈希表的性能。
- 尽可能多的合理实用,由类别Object定义的hashCode方法确保为不同对象返回不同的整数。
//Object定义的hashCode()方法为不同的对象返回不同的整数
//有些时候对象的HashCode就是其在内存中的内存地址
//在写重写hashCode()方法的时候要确保hashCode值不相同。
public class ObHashCode {
public static void main(String[] args) {
Student student = new Student();
student.id = 6;
student.name = "张三";
System.out.println(student.hashCode());
}
}
class Student {
public int id;
public String name;
//重写hashCode()时,自动生成hashCode()的同时也会生成一个equals(Object o)。
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return id == student.id && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
}
Object类方法 - equals
public boolean equals(Object obj)
- 指示一些其他对象是否等于此。obj 是与之比较的参考对象。如果此对象与obj参数相同true; 否则false。
- equals方法在非空对象引用上实现等价关系:
- 自反性 :对于任何非空的参考值x , x.equals(x)应该返回true 。
- 它是对称的 :对于任何非空引用值x和y , x.equals(y)应该返回true当且仅当y.equals(x)回报true 。
- 传递性 :对于任何非空引用值x , y和z ,如果x.equals(y)回报true个y.equals(z)回报true ,然后x.equals(z)应该返回true 。
- 它是一致的 :对于任何非空引用值x和y ,多次调用x.equals(y)始终返回true或始终返回false ,没有设置中使用的信息equals比较上的对象被修改。
- 对于任何非空的参考值x , x.equals(null)应该返回false 。
- 该equals类方法Object实现对象上差别可能性最大的相等关系; 也就是说,对于任何非空的参考值x和y ,当且仅当x和y引用相同的对象( x == y具有值true )时,该方法返回true 。
- 请注意,无论何时覆盖该方法,通常需要覆盖hashCode方法,以便维护hashCode方法的通用合同,该方法规定相等的对象必须具有相等的哈希码。
//如何比较两个对象:
//基本数据类型:比较值
//引用数据类型:比较地址
//对象中的内容:必须重写equals方法。
public class ObEquals {
public static void main(String[] args) {
Star star1 = new Star(1,"张三","唱跳");
Star star2 = new Star(1,"李四","rap");
//比较的是内存中的地址,而不是对象的属性中具体的值
System.out.println(star1 == star2);
//equals 比较内存中的地址
System.out.println(star1.equals(star2));
}
}
class Star{
public int id;
public String name;
public String info;
public Star(int id, String name, String info) {
this.id = id;
this.name = name;
this.info = info;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Star star = (Star) o;
return id == star.id;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
/*
比较的对象如果是一个组合关系,切记要重写自定义属性类的Equals方法
否则自定义性类就会调Object的Equals方法
*/
public class ObEquals2 {
public static void main(String[] args) {
Computer computer = new Computer(1,"a",new CPU(11,"aa"));
Computer computer2 = new Computer(1,"b",new CPU(11,"bb"));
//内存地址
System.out.println(computer == computer2);
//属性的值
System.out.println(computer.equals(computer2));
}
}
class Computer{
public int id;
public String name;
public CPU cpu;
public Computer(int id, String name, CPU cpu) {
this.id = id;
this.name = name;
this.cpu = cpu;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Computer computer = (Computer) o;
return id == computer.id && Objects.equals(cpu, computer.cpu);
}
@Override
public int hashCode() {
return Objects.hash(id, cpu);
}
}
class CPU{
public int id;
public String name;
public CPU(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CPU cpu = (CPU) o;
return id == cpu.id;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
- hashCode 与 equals
/*
如果一个类有很多属性,如何比较对象相等?
如果有很多对象,如何快速找到两个相等的对象?
*如果两个对象equals,那么他们的hashCode一定是相等的。*
*如果两个对象hashCode相等,他们不一定equals ;数量特别多,超出了hashCode的范围*
->需要先验证hashCode,再验证equals
*/
public class ObEquals3 {
public static void main(String[] args) {
Teacher teacher = new Teacher(1,"张三");
Teacher teacher2 = new Teacher(1,"李四");
System.out.println(teacher.hashCode());
System.out.println(teacher2.hashCode());
System.out.println(teacher.equals(teacher2));
}
}
class Teacher{
public int id;
public String name;
public Teacher(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Teacher teacher = (Teacher) o;
return id == teacher.id ;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
- 重写equals、hashCode方法
public class EqualsRewrite {
public static void main(String[] args) {
Person person = new Person("zhangsan",18);
Person person1 = new Person("zhangsan",18);
System.out.println(person.equals(person1));
}
}
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
if (o instanceof Person){
return this.name.equals(((Person) o).name) && this.age == ((Person) o).age;
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
Object类方法 - clone
- protected Object clone() throws CloneNotSupportedException
- 创建并返回此对象的副本(克隆)。
- 按照惯例,此方法返回的对象应该与此对象(正被克隆)无关。 为了实现这一独立性,可能需要修改super.clone返回的对象的一个或多个字段。 通常,这意味着复制构成被克隆的对象的内部“深层结构”的任何可变对象,并通过引用该副本替换对这些对象的引用。 如果一个类仅包含原始字段或对不可变对象的引用,则通常情况下, super.clone返回的对象中的字段通常不需要修改。
- clone的方法Object执行特定的克隆操作。 首先,如果此对象的类不实现接口Cloneable ,则抛出CloneNotSupportedException 。 请注意,所有数组都被认为是实现接口Cloneable ,并且数组类型 T[] 的clone方法的返回类型是 T[] ,其中T是任何引用或原始类型。 否则,该方法将创建该对象的类的新实例,并将其所有字段初始化为完全符合该对象的相应字段的内容,就像通过赋值一样。 这些字段的内容本身不被克隆。 因此,该方法执行该对象的“浅拷贝”,而不是“深度拷贝”操作。
- Object类本身并不实现接口Cloneable ,因此在类别为Object的对象上调用clone方法将导致运行时抛出异常。
clone - 浅拷贝
//被复制对象的所有值属性都含有与原来对象的相同,而所有的对象引用属性仍然指向原来的对象。
public class ObCloneShallow {
public static void main(String[] args) throws CloneNotSupportedException {
Car car = new Car(11,new Engine(12,"v8"),new Tire(13,"米其林"));
Car car2 = (Car) car.clone();
System.out.println(car.toString());
System.out.println(car2.toString());
}
}
//Cloneable接口没有方法,但是使用clone就必须使用该接口。
//否则抛出 CloneNotSupportedException 异常
class Car implements Cloneable{
public int cid;
public Engine engine;
public Tire tire;
public Car(int cid, Engine engine, Tire tire) {
this.cid = cid;
this.engine = engine;
this.tire = tire;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "Car{" +
"cid=" + cid +
", engine=" + engine +
", tire=" + tire +
'}';
}
}
class Engine {
public int eid;
public String ename;
public Engine(int eid, String ename) {
this.eid = eid;
this.ename = ename;
}
}
class Tire {
public int tid;
public String tname;
public Tire(int tid, String tname) {
this.tid = tid;
this.tname = tname;
}
}
输出结果:
Car{cid=11, engine=commonClasses.Engine@4554617c, tire=commonClasses.Tire@74a14482}
Car{cid=11, engine=commonClasses.Engine@4554617c, tire=commonClasses.Tire@74a14482}
clone - 深拷贝
//在浅拷贝的基础上,所有引用其他对象的变量也进行了clone,并指向被复制过的新对象。
public class ObCloneDeep {
public static void main(String[] args) throws CloneNotSupportedException {
CarDeep carDeep = new CarDeep(11,new EngineDeep(12,"v8"),new TireDeep(13,"米其林"));
CarDeep carDeep2 = (CarDeep) carDeep.clone();
System.out.println(carDeep);
System.out.println(carDeep2);
carDeep.engine.ename="c8";
System.out.println(carDeep.engine.ename + "--" + carDeep2.engine.ename);
carDeep.tire.tname="红旗";
System.out.println(carDeep.tire.tname + "--" + carDeep2.tire.tname);
}
}
class CarDeep implements Cloneable{
public int cid;
public EngineDeep engine;
public TireDeep tire;
public CarDeep(int cid, EngineDeep engine, TireDeep tire) {
this.cid = cid;
this.engine = engine;
this.tire = tire;
}
@Override
public Object clone() throws CloneNotSupportedException {
//carDeep是被克隆对象
CarDeep carDeep = (CarDeep) super.clone();
//EngineDeep的深拷贝
carDeep.engine = (EngineDeep) this.engine.clone();
//TireDeep的深拷贝
carDeep.tire = (TireDeep) this.tire.clone();
return carDeep;
}
@Override
public String toString() {
return "CarDeep{" +
"cid=" + cid +
", engine=" + engine +
", tire=" + tire +
'}';
}
}
class EngineDeep implements Cloneable{
public int eid;
public String ename;
public EngineDeep(int eid, String ename) {
this.eid = eid;
this.ename = ename;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class TireDeep implements Cloneable{
public int tid;
public String tname;
public TireDeep(int tid, String tname) {
this.tid = tid;
this.tname = tname;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
输出结果:
CarDeep{cid=11, engine=commonClasses.EngineDeep@4554617c, tire=commonClasses.TireDeep@74a14482}
CarDeep{cid=11, engine=commonClasses.EngineDeep@1540e19d, tire=commonClasses.TireDeep@677327b6}
c8--v8
红旗--米其林
System类
- System类位于java.lang包中,System类包含几个有用的类字段和方法。 它不能被实例化。
- System类提供的System包括标准输入,标准输出和错误输出流; 访问外部定义的属性和环境变量; 一种加载文件和库的方法; 以及用于快速复制阵列的一部分的实用方法。
- System.in 标准输入流,准备提供输入数据。通常,该流对应于键盘输入或由主机环境或用户指定的另一个输入源。
- System.out 标准输出流,准备提供输出数据。通常,此流对应于显示输出或由主机环境或用户指定的另一个输出目标。对于简单的独立Java应用程序,编写一行输出数据的典型方法是: System.out.println(data)。
包装类
常用属性方法
- Java并不是纯面向对象的语言。Java语言是一个面向对象的语言,但是Java中的基本数据类型却是不面向对象的。但是我们在实际使用中经常需要将基本数据转化成对象,便于操作。在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数据类型对应的类统称为包装类(Wrapper class)。
- 包装类均位于java.lang包,包装类和基本数据类型的对应关系如下表所示:
基本数据类型 | 包装类 |
---|---|
byte | Byte |
boolean | Boolean |
short | Short |
char | Character |
int | Integer |
long | Long |
float | Float |
double | Double |
public class Wrapper {
public static void main(String[] args) {
int number = 10; //int数据类型的数字无法直接使用方法。
Integer number2 = 10;
//Integer类的数字可以使用hashCode\toString\equals\doubleValue\parseInt\compareTo等方法
//类型转换: .parse···()
String a = "123";
String b = "456";
String c = "123.4";//Integer.parseInt(c) 不匹配,报错NumberFormatException
System.out.println(Integer.parseInt(a) + Integer.parseInt(b));//579
System.out.println(Double.parseDouble(c) + Double.parseDouble(b));//579.4
System.out.println(Integer.parseInt(a) + "_" + Integer.parseInt(b));//123_456
//最大最小值: .MAX_VALUE \ .MIN_VALUE
System.out.println(Integer.MAX_VALUE + "--" + Integer.MIN_VALUE);
System.out.println(Double.MAX_VALUE + "--" + Double.MIN_VALUE);
//进制转换: .toBinaryString() \ .toOctalString() \ .toHexString()
int d = 10;
System.out.println(Integer.toBinaryString(d));//二进制
System.out.println(Integer.toOctalString(d));//八进制
System.out.println(Integer.toHexString(d));//十六进制
//打印原本数据类型: .TYPE
System.out.println(Integer.TYPE);
//将String解码为Integer: .decode()
System.out.println(Integer.decode(a));
//求和: .sum()
System.out.println(Integer.sum(10, 20));
//将基本类型int转换为包装类型Integer,或者将String转换成Integer,
// String如果为Null或“”都会报错
System.out.println(Integer.valueOf("11"));
System.out.println(Integer.valueOf(11));
//System.out.println(Integer.valueOf(null));//NumberFormatException
}
}
自动装箱拆箱
- 就是将基本类型和包装类进行自动的互相转换。
- 自动装箱的过程:每当需要一种类型的对象时,这种基本类型就自动地封装到与它相同类型的包装中。
- 自动拆箱的过程:每当需要一个值时,被装箱对象中的值就被自动地提取出来,没必要再去调用intValue()和doubleValue()方法。
- 自动装箱与拆箱的功能事实上是编译器来完成的,编译器在编译时期依您所编写的语法,决定是否进行装箱或拆箱动作。
public class Boxing {
public static void main(String[] args) {
//创建对象的方法:
Integer i = Integer.valueOf(11);
//自动装箱 底层使用Integer.valueOf()
Integer i2 = 12;
//自动拆箱 底层使用intValue()
//Integer.valueOf(13);是Integer.valueOf(13).intValue();的语法糖
int i3 = Integer.valueOf(13);
int i4 = Integer.valueOf(14).intValue();
}
}
public class Test {
public static void main(String[] args) {
int a = 10;
Integer b = 10;
// + - * / == 运算时会进行拆箱操作(基本类型)
System.out.println(a == b);//true
// equals() 方法 会进行自动装箱操作(包装类)
System.out.println(b.equals(a));//true
}
}
//equals() 对应的源代码
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
//缓存分析
public class Cache {
public static void main(String[] args) {
//使用int类型的默认缓存,缓存区间[-128,127]
Integer i1 = Integer.valueOf(-128);
Integer i2 = Integer.valueOf(-128);
System.out.println(i1 == i2);//true
//不使用缓存,在堆内存中创建对象
Integer i3 = new Integer(10);
Integer i4 = new Integer(10);
System.out.println(i3 == i4);//false
//不使用缓存,在堆内存中创建对象,因为超出了缓存区间的范围
Integer i5 = Integer.valueOf(1111);
Integer i6 = Integer.valueOf(1111);
System.out.println(i5 == i6);//false
//自动装箱,默认使用Integer.valueOf()方法
Integer i7 = 11;
Integer i8 = 11;
System.out.println(i7 == i8);//true
}
}
//valueOf() 对应的源代码
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
包装类 与 基本数据类型 与 String类型 相互转换
- 基本数据类型与包装类转换
public class Conversion {
public static void main(String[] args) {
/* 基本数据类型 转 包装类
方式一:public Integer()构造器,JDK9版本后过时
方式二:自动装箱
方式三:public static Integer valueOf()方法
*/
int i = 123;
Integer integer1 = new Integer(i);
Integer integer2 = i;
Integer integer3 = Integer.valueOf(i);
System.out.println(integer1);//123
System.out.println(integer2);//123
System.out.println(integer3);//123
/* 包装类 转 基本数据类型
方式一:自动拆箱
方式二:public int intValue()方法
*/
Integer integer4 = new Integer(456);
int i1 = integer4;
int i2 = integer4.intValue();
System.out.println(i1);//456
System.out.println(i2);//456
}
}
- 包装类与String类型转换
public class Conversion2 {
public static void main(String[] args) {
/* 包装类 转 String类型
方式一:与空字符串拼接
方式二:public String toString()方法
*/
Integer integer = new Integer(123);
String str1 = integer+"asd";
String str2 = integer.toString();
System.out.println(str1);//123asd
System.out.println(str2+23);//12323
/* String类型 转 包装类
方式一:public Integer()构造器
当使用String转换成数值型数据时,String类型的值也必须是数值
无法将String类型的数据转换成char/character
当String类型转换成boolean/Boolean类型时
若String类型的值不是true/false,转换的结果一定是false,此时的结果不是布尔型,表示的错误转换
当且仅当String类型的值为true/false,转换的结果才是布尔型
方式二:public static Integer parseInt()方法
*/
String str3 = "123";
String str4 = "a";
String str5 = "true";
String str6 = "false";
Integer integer1 = new Integer(str3);
//Integer integer2 = new Integer(str4);//NumberFormatException
//Character character = new Character(str4);
Boolean boolean1 = new Boolean(str4);
Boolean boolean2 = new Boolean(str5);
Boolean boolean3 = new Boolean(str6);
System.out.println(integer1);//123
System.out.println(boolean1);//false
System.out.println(boolean2);//true
System.out.println(boolean3);//false
Integer integer2 = Integer.parseInt(str3);
System.out.println(integer2);//123
}
}
- 基本数据类型与String类型转换
public class Conversion3 {
public static void main(String[] args) {
/* 基本数据类型 转 String类型
方式一:与空字符串拼接
方式二:public static String valueOf()方法
*/
int a = 123;
char c = 'a';
String str1 = a + " asd";
String str2 = c + " asd";
System.out.println(str1);//123 asd
System.out.println(str2);//a asd
String str3 = String.valueOf(a);
String str4 = String.valueOf(c);
System.out.println(str3);//123
System.out.println(str4);//a
/* String类型 转 基本数据类型
public static int parseInt()方法
*/
String str5 = "123";
String str6 = "a";
int i1 = Integer.parseInt(str5);
//int i2 = Integer.parseInt(str6);//NumberFormatException
System.out.println(i1);//123
}
}
字符串相关类
- String 类 代表不可变的字符序列
- StringBuilder类、StringBuffer类 代表可变的字符序列
String
- Java中字符串对象创建有两种形式。
- 一种为字面量形式。
String str="Zhang San";
- 一种使用new这种标准的构造对象的方法.
String str new string("Zhang San");
- 一种为字面量形式。
- 这两种方式我们在代码编写时都经常使用,尤其是字面量的方式。
- 然而这两种实现其实存在着一些性能和内存占用的差别。这一切都是源于JVM为了减少字符串对象的重复创建,其维护了一个特殊的内存,这段内存被称为字符串常量池或者字符串字面量池。
public class StringTest {
public static void main(String[] args) {
//创建一个字符串
String a = "张三";//a在栈地址 指向String常量池的“张三”,
String b = new String("张三");//“张三”会创建一个对象,在堆地址
String c = "张三";
System.out.println(a == b);//false a在栈地址,c在堆地址
System.out.println(a == c);//true !!!a和c都在栈地址
System.out.println("张三" == a);//true
System.out.println("张三" == b);//false
System.out.println(a.equals(b));//true
//字符串推荐使用 equals() 方法比较
}
}
String 与 byte[]数值数组 、char[]字符数组 的转换
public class StringByte {
public static void main(String[] args) {
/*
String类 转 byte[] :
public byte[] getBytes()
字符串包含中文汉字、符号, gbk编码 1汉字 == 2字节
utf-8编码 1汉字 == 3字节
英文符号 1符号 == 1字符
*/
String str = "红酒?";
byte[] bytes = str.getBytes();
try {
byte[] gbks = str.getBytes("gbk");
System.out.println(Arrays.toString(gbks));[-70, -20, -66, -58, 63]
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
System.out.println(bytes.length);//7
System.out.println(Arrays.toString(bytes));//[-25, -70, -94, -23, -123, -110,63]
/*
byte[] 转 String类 :
public String(byte[] bytes, int offset, int length)
bytes - 要解码为字符的字节
offset - 要解码的第一个字节的索引
length - 要解码的字节数
*/
String strByte = new String(bytes,0,bytes.length);
System.out.println(strByte);//红酒?
String strByte1 = new String(bytes,0,bytes.length-2);
System.out.println(strByte1);//红� 如果长度不足,返回�
}
}
public class StringChar {
public static void main(String[] args) {
/*
String类 转 char[] :
public char[] toCharArray()
*/
String str = "林黛玉倒拔垂杨柳!";
char[] chars = str.toCharArray();
System.out.println(Arrays.toString(chars));//[林, 黛, 玉, 倒, 拔, 垂, 杨, 柳, !]
/*
char[] 转 String类 :
public String(char[] value, int offset, int count)
value - 作为字符源的数组
offset - 初始偏移量
count - 长度
*/
String strChar = new String(chars,3,5);
System.out.println(strChar);//倒拔垂杨柳
}
}
String方法 - 判断
//字符串的方法(1)
public class StringTest {
public static void main(String[] args) {
String a = "Zhang San";
String b = "";
String c = null;
System.out.println(a.length());//9 (返回字符串的长度)
System.out.println(a.isEmpty());//false (判断字符串是否为空)
// b 为空字符串,在常量池中; null没有地址值
System.out.println(b.isEmpty());//true
//System.out.println(c.isEmpty());//NullPointerException
System.out.println(a.startsWith("zh"));//true (判断字符串用xx开头)
System.out.println(a.startsWith("s"));//false
System.out.println(a.endsWith("an"));//true (判断字符串用xx结尾)
System.out.println(a.endsWith("sn"));//false
System.out.println(a.toUpperCase());//ZHANG SAN (字符串所有英文大写)
System.out.println(a.toLowerCase());//zhang san (字符串所有英文小写)
}
}
String方法 - 查询
//字符串的方法(2)
public class StringTest {
public static void main(String[] args) {
String a = "Zhang San";
//String是一个char类型的数组, charAt()返回的是指定下标对应的字符
System.out.println(a.charAt(2));//a
//System.out.println(a.charAt(a.length()));//StringIndexOutOfBoundsException
//indexOf() 根据指定字符串查询指定下标,只返回查询到的第一个元素的下标,查询不到返回-1
System.out.println(a.indexOf("a"));//2
System.out.println(a.indexOf("ang"));//2
System.out.println(a.indexOf("b"));//-1
System.out.println(a.indexOf("a", 5)); //7 (从指定位置开始查询下标)
//lastIndexOf() 是indexOf()的逆向查询
System.out.println(a.lastIndexOf("a"));//7
System.out.println(a.lastIndexOf("a", 6));//2
//substring() 按指定下标截取字符串
System.out.println(a.substring(2));//ang San
System.out.println(a.substring(2, 8)); //ang Sa
}
}
String方法 - 判断、拼接、分割、去空格
//字符串的方法(3)
public class StringTest {
public static void main(String[] args) throws UnsupportedEncodingException {
String a = "Zhang San";
String b = "Zhang San 风";
byte[] bytes = a.getBytes();
byte[] bytes1 = b.getBytes();
//System.out.println(Arrays.toString(bytes));//[90, 104, 97, 110, 103, 32, 83, 97, 110]
//System.out.println(Arrays.toString(bytes1));//[90, 104, 97, 110, 103, 32, 83, 97, 110, 32, -23, -93, -114]
String c = new String(bytes1,"GBK");//对字符串进行重新编码
System.out.println(c);//Zhang San 椋�
String d = "zh-ang-s-an";
//contains() 判断是否包含指定字符串
System.out.println(d.contains("zh"));//true
System.out.println(d.contains("y"));//false
//replace()\replaceAll() 替换指定字符串内容。区别:replaceAll()支持正则表达式
System.out.println(d.replace("a", "e"));//zh-eng-s-en
System.out.println(d.replaceAll("a", "e"));//zh-eng-s-en
//concat() 字符串的拼接
System.out.println(d.concat("xyz"));//zh-ang-s-anxyz
System.out.println(d + "xyz");//zh-ang-s-anxyz
//String字符串是不可更改的 只能新建
d.concat("a");
d.concat("b");
d.concat("c");
System.out.println(d);//zh-ang-s-an
d = d.concat("a"); //地址发生变化
d = d.concat("b");
d = d.concat("c");
System.out.println(d);//zh-ang-s-anabc (经历了四个对象,资源浪费)
//split() 按照指定字符串进行分割 ,返回值是一个 String 数组
String[] strings = d.split("-");
System.out.println(Arrays.toString(strings));//[zh, ang, s, anabc]
//trim() 去除字符串开头和结尾的空格
String e = " zhang san ";
System.out.println("-->|"+e+"|<--");
System.out.println("-->|"+e.trim()+"|<--");
}
}
String方法 - 比较
//字符串的方法(4)
public class StringTest {
public static void main(String[] args) throws UnsupportedEncodingException {
String a = "zhang";
String b = "zhang";
String c = "Zhang";
String d = "Zheng";
String e = "zheng";
String f = "zhangsan";
String g = "zhengsan";
//compareTo()\compareToIgnoreCase() 对字符串进行比较 。 区别:compareToIgnoreCase()忽略大小写
System.out.println(a.compareTo(b));//0
System.out.println(a.compareTo(c));//32 (返回第一次出现不一致的ASCII 差值)
System.out.println(a.compareTo(d));//32 (比较完第一位,不同时不向后继续比较)
System.out.println(a.compareTo(e));//-4
System.out.println(a.compareTo(f));//-3
// 长度不一致时,若前部分一致,返回长度的差值
System.out.println(a.compareTo(g));//-4
// 长度不一致时,若前部分不一致。返回第一次出现不一致的ASCII 差值
System.out.println(a.compareToIgnoreCase(c));//0 (compareToIgnoreCase不区分大小写)
}
}
String 源码分析
public final class String//final --> String不能被继承(最终类)
private final char value[];//String是一个字符数组。
public int length() {//长度: 方法返回的是数组的长度
return value.length;
}
public boolean isEmpty() {//是否为空: 数组长度是否为零
return value.length == 0;
}
public char charAt(int index) {
if ((index < 0) || (index >= value.length)) {
throw new StringIndexOutOfBoundsException(index);
//数组下标越界异常
}
return value[index];
}
public boolean equals(Object anObject) {
if (this == anObject) {//是否为同一个对象
return true;
}
if (anObject instanceof String) {//是否为String
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {//判断长度是否相等
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {//逐个比较
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
//1.如果不是String类型,直接返回false
//2.String长度不相同直接返回false
}
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;//返回一个差值
}
public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
int len = value.length;
//拼接实际是复制原来的数组,并把数组的长度增长
char buf[] = Arrays.copyOf(value, len + otherLen);
str.getChars(buf, len);
return new String(buf, true);//每次拼接都会新建一个数组
}
StringBuilder
- StingBuffer和StringBuilder非常类似,均为可变字符序列。这两个类都是抽象类AbstractStringBuilder的子类,方法几乎完全相同
- 区别:
- StringBuffer:线程安全,做线程同步检查,效率较低
- StringBuilder:线程不安全,不做线程同步检查,因此效率较高
//效率比较
public class StringBuilderTest {
public static void main(String[] args) {
//String a = "zhang san";
//long t = System.currentTimeMillis();
//for (int i = 0; i < 100_000; i++) {
// a = a.concat("san");
//}
//long t1 = System.currentTimeMillis();
//System.out.println(t1 - t);//6530(ms)
StringBuilder builder = new StringBuilder("zhang san");
long t = System.currentTimeMillis();
for (int i = 0; i < 100_000; i++) {
builder.append("san");
}
long t1 = System.currentTimeMillis();
System.out.println(t1 - t);//6(ms)
}
}
StringBuilder 方法
public class StringBuilderTest {
public static void main(String[] args) {
String a = "zhang san";
StringBuilder builder = new StringBuilder("zhang san");
builder.append("san");//append() 内容追加
System.out.println(builder);//zhang sansan
builder.insert(3,"san");//insert() 在指定位置追加内容
System.out.println(builder);//zhasanng sansan
System.out.println(builder.charAt(1));//2 charAt() 取出指定下标字符
builder.setCharAt(3,'e');//给指定位置设置'字符'
System.out.println(builder);//zhaeanng sansan
builder.replace(1,3,"bbb");//(1,3)进行指定字符替换
System.out.println(builder);//zbbbeanng sansan
builder.deleteCharAt(3);//删除指定位置的字符
System.out.println(builder);//zbbeanng sansan
builder.delete(1,3);//删除多个字符
System.out.println(builder);//zeanng sansan
builder.reverse();//倒叙输出字符串
System.out.println(builder);//nasnas gnnaez
}
}
//String 与 StringBuilder 相互转换
public class StringBuilderTest {
public static void main(String[] args) {
String a = "zhang san";
//将 String 转换为 StringBuilder
StringBuilder builder = new StringBuilder(a);
//StringBuilder 转换为字符串
String b = builder.toString();
}
}
StringBuilder 源码分析
public final class StringBuilder
extends AbstractStringBuilder //继承AbstractStringBuilder类
implements java.io.Serializable, CharSequence{
public StringBuilder() {//无参,默认数组长度16
super(16);
}
public StringBuilder(int capacity) {//int参数,定义数组长度
super(capacity);
}
public StringBuilder(String str) {
super(str.length() + 16);//字符串长度+16位缓存
append(str);
}
}
char[] value; //可更改字符数组
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 void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
//如果扩容:数组长度*2+2
if (minimumCapacity - value.length > 0) {
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
}
}
public class StringBuilderTest {
public static void main(String[] args) {
StringBuilder builder = new StringBuilder("zhang san");
System.out.println("真实内容长度:" + builder.length());//9
System.out.println("底层数组长度:" + builder.capacity());//25
for (int i = 0; i < 16; i++) {
builder.append("a");
}
System.out.println("真实内容长度:" + builder.length());//25
System.out.println("底层数组长度:" + builder.capacity());//25
builder.append("b");
System.out.println("底层数组长度:" + builder.capacity());//52(扩容1)
for (int i = 0; i < 26; i++) {
builder.append("b");
}
System.out.println("底层数组长度:" + builder.capacity());//52(扩容1)
builder.append("c");
System.out.println("底层数组长度:" + builder.capacity());//106(扩容2)
}
}
Date类
public class DateTest {
public static void main(String[] args) {
Date date = new Date(0);
System.out.println(date);//Thu Jan 01 08:00:00 CST 1970
Date date1 = new Date();
System.out.println(date1);//获取当前时间
//System.out.println(date.getYear());//1900到现在的差值
//System.out.println(date.getMonth());//0-11
//System.out.println(date.getDate());//当前 月 的第几天
//System.out.println(date.getDay()); //当前 周 的第几天
//System.out.println(date.getHours());//时
//System.out.println(date.getMinutes());//分
//System.out.println(date.getSeconds());//秒
System.out.println(date1.getTime());//1970年1月1日8:00到现在的毫秒数
System.out.println(date1.toLocaleString());//获取当前时间 年-月-日 时:分:秒
}
}
DateFormat类
yyyy | 年 |
MM | 月 |
dd | 日 |
DD | 当年第几天 |
HH | 时(24进制) |
hh | 时(12进制) |
mm | 分 |
ss | 秒 |
SS | 毫秒 |
aa | 上下午 |
EE | 星期几 |
public class DateFormatTest {
public static void main(String[] args) throws ParseException {
Date date = new Date();
System.out.println(date);//Thu Jan 26 18:44:06 CST 2023
//设置时间格式 DateFormat类
DateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");
//调用格式化方法
String formatTime = dateFormat.format(date);//format方法转换为String类型
System.out.println(formatTime);//2023年01月26日 06:44:06
//String类型转为Date类型:parse(str) str:yyyy-MM-dd hh:mm:ss
DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date parseTime = dateFormat2.parse(dateFormat2.format(date));
System.out.println(parseTime);//2023-01-26 06:47:33
}
}
Calendar类
- Calendar类是一个抽象类,不能直接new对象。
public class CalendarTest {
public static void main(String[] args) {
//获取日历类
//Calendar类是一个抽象类,不能直接new对象。
//getInstance方法底层实例化 Calendar的唯一子类对象
Calendar calendar = Calendar.getInstance();
System.out.println(calendar);
//java.util.GregorianCalendar[time=1677582837253,areFieldsSet=true,···
// time表示当前系统的毫秒数
//设置指定时间的值
System.out.println("设置指定时间的值");
calendar.set(2023,10,11,20,00,00);//年月日时分秒
calendar.setTime(new Date(3000_0000L));//使用给定的 Date设置此日历的时间
calendar.setTimeInMillis(3000_0000L);//从给定的长值设置此日历的当前时间。
//获取指定时间的值
System.out.println("获取指定时间的值");
System.out.println("year "+calendar.get(Calendar.YEAR));//年
System.out.println("month "+calendar.get(Calendar.MONTH)+1);//月 [0,11]
System.out.println("day "+calendar.get(Calendar.DAY_OF_MONTH));//日
System.out.println("hour "+calendar.get(Calendar.HOUR_OF_DAY));//时(24进制)
System.out.println("minute "+calendar.get(Calendar.MINUTE));//分
System.out.println("second "+calendar.get(Calendar.SECOND));//秒
System.out.println(calendar.get(Calendar.DAY_OF_WEEK)-1);//星期几 (周日是第一天)
System.out.println(calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH));//当前月的第几周
System.out.println(calendar.get(Calendar.HOUR));//时(12进制)
System.out.println(calendar.get(Calendar.MILLISECOND));//毫秒
//Calendar 转 Date
System.out.println("Calendar 转 Date");
Date dateTime = calendar.getTime();
System.out.println(dateTime);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
System.out.println(simpleDateFormat.format(dateTime));
//获取当前时间
System.out.println("获取当前时间");
Instant now = Instant.now();
System.out.println(now);//年-月-日T时:分:秒.xxxz
//System.out.println(now.MAX);//+1000000000-12-31T23:59:59.999999999Z
//System.out.println(now.MIN);//-1000000000-01-01T00:00:00Z
//System.out.println(now.EPOCH);//1970-01-01T00:00:00Z
LocalDate localDate = LocalDate.now();
System.out.println(localDate);//年-月-日
//格式化输出
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
String formatTime = localDate.format(dateTimeFormatter);
System.out.println(formatTime);
//String 转 Date
LocalDate parseTime = LocalDate.parse("1970-08-01");
System.out.println(parseTime);
}
}
Math类
public class MathTest {
public static void main(String[] args) {
System.out.println(Math.PI);//PI 圆周率 3.141592653589793
System.out.println(Math.E); //E 对数常量 2.718281828459045
System.out.println(Math.round(3.14));//四舍五入 3
System.out.println(Math.round(3.71));//四舍五入 4
System.out.println(Math.ceil(3.14)); //向上取整 4.0
System.out.println(Math.floor(3.72));//向下取整 3.0
System.out.println(Math.random());//[0,1]随机数
System.out.println(Math.sqrt(64));//开平方 8.0
System.out.println(Math.pow(2, 5));//m的n次幂 32.0
System.out.println(Math.abs(-5));//取绝对值 5
System.out.println(Math.max(1, 3));//两数取大 3
System.out.println(Math.min(1, 4));//两数取小 1
}
}
Random类
public class RandomTest {
public static void main(String[] args) {
Random random = new Random();
System.out.println(random.nextInt(10));//产生[0,10)随机整数
System.out.println(random.nextInt(9000) + 1000);//产生[1000,9999)随机整数
//伪随机数 输出值确定
Random random2 = new Random(10);
System.out.println(random2.nextInt(15));
System.out.println(random2.nextInt(10));
}
}
UUID类
- UUID是Universally Unique IDentifier的缩写,翻译为通用唯一标识符或者全局唯一标识符。
- UUID是一种软件构建的标准,也是开放软件基金会组织在分布式计算环境领域的一部分。提出此标准的目的是:让分布式系统中的所有元素或者组件都有唯一的可辨别的信息,因为极低冲突频率和高效算法的基础,它不需要集中式控制和管理唯一可辨别信息的生成,由此,每个使用者都可以自由地创建与其他人不冲突的UUID。
- 目前有五种版本
- 版本1:基于时间的UUID
- 版本2:DCE安全的UUID (和版本1类似)
- 版本3:基于名字的UUID(MD5)
- 版本4:基于加密的强随机数的UUID
- 版本5:基于名字的UUID(SHA1)
-
四种生成方式
-
最常见的就是调用 静态方法UUID#randomUUID(),这就是版本4的静态工厂方法
-
其次是调用 静态方法UUID#nameUUIDFromBytes(byte[] name),这就是版本3的静态工厂方法
-
另外有调用 静态方法UUID#fromString(String name),这是解析8-4-4-4-12格式字符串生成UUID实例的静态工厂方法
-
还有低层次的 构造函数UUID(long mostSigBits, long leastSigBits),这个对于使用者来说并不常见
-
BigDecimal
- BigDecimal类位于java.math包中,BigDecimal类提供了算术,缩放操作,舍入,比较,散列和格式转换的操作。
- 与金融有关的相关计算可以使用BigDecimal类,参数通常使用字符串
public class BigDecimalTest {
public static void main(String[] args) {
/*
加: add(BigDecimal augend) 其值是 (this + augend)
减: subtract(BigDecimal subtrahend) 其值是 (this - subtrahend)
乘: multiply(BigDecimal multiplicand) 其值是 (this × multiplicand)
除: divide(BigDecimal divisor) 其值为(this / divisor)
divide(BigDecimal divisor, int roundingMode) 其值是 (this / divisor)
divide(BigDecimal divisor, int scale, int roundingMode) 其值为 (this / divisor)
参数:
scale:保留几位小数
roundingMode:舍入方式枚举值
ROUND_UP == 0 // 无论正负,当小数位有值、并且大于0,正数向正无穷进1,负数向负无穷进1(与第二条相反)
例: 值:1.2 舍入结果:2
值:-1.2 舍入结果:-2
ROUND_DOWN == 1 // 无论正负,当小数位有值、并且大于0,正数向0进1,负数向0进1(与第一条相反)
例: 值:1.9 舍入结果:1
值:-1.2 舍入结果:-1
ROUND_CEILING == 2 // 无论正负,当小数位有值、并且大于0,向比自身大的方向进1(与第四条相反)
例: 值:2.1 舍入结果:3
值:-1.9 舍入结果:-1
BigDecimal.ROUND_FLOOR == 3 // 无论正负,当小数位有值、并且大于0,向比自身小的方向进1(与第三条相反)
例: 值:2.9 舍入结果:2
值:-1.1 舍入结果:-2
ROUND_HALF_UP == 4 // 经典四舍五入
例: 值:2.4 舍入结果:2
值:2.5 舍入结果:3
值:-1.1 舍入结果:-1
ROUND_HALF_DOWN == 5 // 五舍六入 和四舍五入的区别:就是:值小于等于5舍去,大于等于6进位
例: 值:2.5 舍入结果:2
值:2.6 舍入结果:3
值:-1.5 舍入结果:-1
ROUND_HALF_EVEN == 6 // 银行家舍入法 “四舍六入五成双”,也即“4舍6入5凑偶”,这里“四”是指≤4时舍去,"六"是指≥6时进上。"五"指的是根据5后面的数字来定,当5后有数时,舍5入1;当5后无有效数字时,需要分两种情况来讲:5前为奇数,舍5入1;5前为偶数,舍5不进
例: 值:5.5 舍入结果:6
值:2.5 舍入结果:2
值:-1.5 舍入结果:-2
值:-2.5 舍入结果:-2
ROUND_UNNECESSARY == 7 // 不进行取舍,如果强行取舍或精度不准确抛出异常java.lang.ArithmeticException
*/
BigDecimal bigDecimal1 = new BigDecimal("3.1415926");
BigDecimal bigDecimal2 = new BigDecimal("2.71828");
System.out.println(bigDecimal1.add(bigDecimal2));//5.8598726
System.out.println(bigDecimal1.subtract(bigDecimal2));//0.4233126
System.out.println(bigDecimal1.multiply(bigDecimal2));//8.539728332728
System.out.println(bigDecimal1.divide(bigDecimal2, 4, BigDecimal.ROUND_HALF_UP));//1.1557
System.out.println(bigDecimal1.divide(bigDecimal2, 4, 4));//1.1557
System.out.println(bigDecimal1.divide(bigDecimal2, 4));//1.1557281
}
}
Enum类
- 枚举就是一种特殊的java类,在这个特殊的类当中定义几个静态变量,每个变 量都是这个类的实例。通过关键字enum实现,自动继承自java.lang.Enum类(枚举类)。
- 枚举(Enum),是指一个经过排序的、被打包成一个单一实体的项列表。一个枚举的实例可以使用枚举项列表中任意单一项的值。
- 通常用来表示诸如颜色、方式、类别、状态等数目有限、形式离散、表达又极为明确的量。
public enum Gender {
男,女
}
public class Student {
private String name;
private Gender sex;
public Student(String name, Gender sex) {
this.name = name;
this.sex = sex;
}
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Gender getSex() {
return sex;
}
public void setSex(Gender sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
'}';
}
}
public class EnumTest {
public static void main(String[] args) {
Student student = new Student("ZhangSan",Gender.男);
}
}