【JAVA BASE API】介绍Java基础API语法,包括JAVA8之后的时间日期等

简介: 【JAVA BASE API】介绍Java基础API语法,包括JAVA8之后的时间日期等


Object 类

Object类是类层次结构的根。每个类都有 Object作为超类。所有对象,包括数组,实现这个类的方法

Object 常见的 API

API 用法
clone() 创建并返回此对象的副本
toString() 返回对象的字符串表现形式
equals(Object obj) 指示是否有其他对象 “等于” 这一个

clone 对象克隆

public class Demo{
  public static void main(String[] args) {
  Person p = new Person(12, "zhangssan");
  Person p1 = null;
  {
    try{
    p1 = (Person)p.clone();
    } catch(CloneNotSupportedException e) {
    e.printStackTrace();
    }
  {
  System.out.println(p); // Person@123456
  System out.println(p1); // Person@114514
  }
}

从这边代码可以看到 p1 使用 clone 方法 克隆 对象 p

地址却是不一样的, 说明我们开辟了一块新的栈内存

浅拷贝 与 深拷贝

  1. 浅拷贝
// Person 类
class Person implements Cloneable {
    private String name;
    private int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override             // throws xxx 异常声明 或使用 try catch
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }
}
// Main 程序入口类
public class Main {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person1 = new Person("Alice", 25);
        Person person2 = (Person) person1.clone();
        System.out.println("person1: " + person1);
        System.out.println("person2: " + person2);
        // 修改person1的字段
        person1.setName("Bob");
        person1.setAge(30);
        // 验证浅拷贝的效果
        System.out.println("person1: " + person1);
        System.out.println("person2: " + person2);
    }
}
  1. 只可以在子类中重写克隆方法, 因为 Main 函数不是类的实例方法, 它无法被继承或重写
  2. 可以看到 Person 类实现了一个接口 Cloneable, 这个 Cloneable 就称之为 标记接口, 它表示该类的实例可以被克隆, 看开看你会发现它只是一个 …{}

运行如下

person1: Person{name='Alice', age=25}
person2: Person{name='Alice', age=25}
person1: Person{name='Bob', age=30}
person2: Person{name='Alice', age=25}
  1. 深拷贝
// Person 类
class Person implements Cloneable {
    private String name;
    private int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override         // throws xxx 异常声明 或使用 try catch
    public Object clone() throws CloneNotSupportedException {
        // 创建新的Person对象
        Person clonedPerson = (Person) super.clone();
        // 修改为深拷贝
        clonedPerson.name = new String(this.name);
        // 对于基本类型,直接复制值
        clonedPerson.age = this.age;
        return clonedPerson;
    }
    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }
}
// Main 程序入口类
public class Main {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person1 = new Person("Alice", 25);
        Person person2 = (Person) person1.clone();
        System.out.println("person1: " + person1);
        System.out.println("person2: " + person2);
        // 修改person1的字段
        person1.setName("Bob");
        person1.setAge(30);
        // 验证深拷贝的效果
        System.out.println("person1: " + person1);
        System.out.println("person2: " + person2);
    }
}

运行如下

person1: Person{name='Alice', age=25}
person2: Person{name='Alice', age=25}
person1: Person{name='Bob', age=30}
person2: Person{name='Alice', age=25}

首先,创建了一个名为 person1Person 对象,其姓名为 "Alice",年龄为 25 然后,通过调用clone() 方法创建了一个名为 person2 的新对象,它与 person1 具有相同的属性值。

在验证深拷贝效果之前,我们修改了 person1 的姓名为 "Bob" ,年龄为 30 最后,输出了 person1person2 的详细信息。

可以看到,person1 的改变没有影响到 person2 ,说明这是一个深拷贝。因此,person1 被成功拷贝到了 person2 它们之间没有共享字段的引用。

toString() 转换字符串

toString() 方法源码

public String toString() {
   return "Person{name='" + name + "', age=" + age + "}"; // 例如有name age字段
}

使用

// 入口函数 Main
public class Main {
    public static void main(String[] args) {
        Person person = new Person("John", 25);
        System.out.println(person.toString());
    }
}

输出: Person{name=“John”, age=25}

equals(Object obj) 地址比较

简单比较两个对象的引用

Object obj1 = new Object();
Object obj2 = obj1;
if (obj1 == obj2) {
    // 两个对象的引用相等
}

判断两个对象的地址是否相等

obj1.equals(obj2);

Objects 类

Objects是一个工具类,提供了很多操作对象的静态方法给我们使用

它与 Object 类有着相同的方法名,功能都是类似的

Objects.equals(Object obj1, Object obj2) 非空比较

Objects.equals 先做非空判断,再做对象比较

源码解析

public static boolean equals(Object a, Object b) {
    return (a == b) || (a != null && a.equals(b));
}

isNull(Object obj) 判断null

判断对象是否为 null 若为 null 返回 true

nonNull(Object obj) 判断非null

判断对象是否不为 null 若不为 null 返回 true

包装类

基本数据类型对应的包装类列表

基本数据类型 包装类
byte Byte
short Short
int Integer
long Long
char Character
float Float
double Double
boolean Boolean

自动装箱

可以自动把基本类型的数据转换成对象

例如

Integer a1 = 12;

自动拆箱

可以自动把包装类型的对象转换成对应基本数据类型

例如

int a4 = a1;

字符串操作 | StringBuilder,StringBuffer,StringJoiner

StringBuilderStringBufferStringJoiner 都是一些字符串的操作方法,它们有时比 String 更适合做字符串的修改操作,效率也会更高,代码也会更简洁

StringBuilder 字符串操作

StringBuilder 在操作字符串的时候效率非常高(频繁拼接,修改建议使用 StringBuilder )

基本使用

StringBuilder s = new StringBuilder();
StringBuilder s = new StringBuilder("hello");
// 拼接内容
s.append(12);
s.append("hi");
s.append(true);
// 返回内容: “hello12hitrue”
// 支持链式编程
s.append(true).append("haha")

使用 StringBuilder 拼接数组

public static void main(String[] args) {
  System.out.println(getArrayList(new int[] {
      1, 123, 456
  }));
}
// 实现方法
public static String getArrayList(int[] arr) {
    if (arr == null) {
        return null;
    }
  // 实例化字符串操作类 StringBuilder
    StringBuilder sb = new StringBuilder();
    sb.append("[");
    for (int i = 0; i < arr.length; i++) {
      if (i == arr.length - 1) { // 若拼接到最后一个不加 ,
        sb.append(arr[i]);
      } else {
        sb.append(arr[i]).append(",");
      }
  }
  sb.append("]");
  return sb.toString(); // 返回 字符串表现形式
}

StringBuffer 字符串操作

StringBuilder 相似,但是 StringBuilder 是线程不安全的,StringBuffer 是线程安全的

StringJoiner 字符串拼接

StringBuilder 相似,也是用来操作字符串的,也可以看成是一个容器,创建之后里面的内容是可变的

好处: 不仅能提高字符串的操作效率,并且在有些场景下使用它操作字符串,代码会更简洁

基本使用

StringJoiner s = new StringJoiner(间隔符号);
StringJoiner s = new StringJoiner(间隔符号, 开始符号, 结束符号);

StringJoiner 相对于 StringBuilder 来说还是比较简单, 一般只可以操作简单的字符拼接,如果需要频繁插入,删除字符,建议使用 StringBuilder 操作

StringJoiner s = new StringJoiner(", ");
s.add("java1");
s.add("java2"); 
// java1, java2
// ----------------------------------
StringJoiner s = new StringJoiner(", ", "[", "]");
s.add("java1");
s.add("java2"); 
// [java1, java2]

使用 StringJoiner 拼接

public static void main(String[] args) {
  System.out.println(getArrayData(new int[] {
      1, 2, 3
  }));
}
public static string getArrayData(int[] arr) {
  // 判断 arr 非空
  if (arr == null) {
    return null;
  }
  // arr 数组存在
  StringJoiner sj = new StringJoiner(", ", "[", "]");
  for(int i = 0; i < arr.length; i++) {
    sj.add(arr[i] + "");
  }
  return sj.toString();
}

MathSystemRuntime

Math 数学类

Math 代表数学,是一个工具类,里面提供的都是对数据进行操作的一些静态方法

System 系统类

System.currentTimeMillis(); // 获取当前系统的时间(毫秒值) long 类型

Runtime 运行类

小知识: Runtime 是个单例设计模式的类

简单使用

Runtime r = Runtime.getRuntime(); // 返回与当前Java应用程序关联的运行时对象

BigDecimal 解决小数失真运算

在一些商业项目中,在进行一些小数运算时,必须要求精准,使用传统运算符时可能会出现小数运算失真的情况

System.out.println(0.2 + 0.1); // 0.30000000000000004

采用 java.util.math 中的 BigDecimal 类 来运算解决失真问题

// 转为 字符串 封装成 BigDecimal 对象来运算
BigDecimal a1 = new BigDecimal(Double.toString(a));
BigDecimal b1 = new BigDecimal(Double.toString(b));
// 优化
// 推荐用以下方式把小数转换为字符串再得到BigDecimal对象来使用(更简洁)
BigDecimal a1 = BiDecimal.valueOf(a);
BigDecimal b1 = BiDecimal.valueOf(b);
BigDecimal b = a1.add(b1);
BigDecimal b = a1.subtract(b1);
BigDecimal b = a1.multiply(b1);
BigDecimal b = a1.divide(b1);

Date 类

before Java 1.8

在 Java 1.8 之前,Date 对象是可变的,所以处理时间类需要谨慎

创建时间对象(部分过时)

Date currentDate = new Date(); // 使用当前日期和时间创建Date对象
Date specificDate = new Date(year, month, day); // 使用指定的年、月、日创建Date对象(过时的)

获取日期和时间(过时的)

int year = date.getYear(); // 获取年份(从1900年开始计算)
int month = date.getMonth(); // 获取月份(从0开始计算,0表示一月)
int day = date.getDate(); // 获取天数(月份中的日期)
int hours = date.getHours(); // 获取小时w
int minutes = date.getMinutes(); // 获取分钟
int seconds = date.getSeconds(); // 获取秒钟

设置日期和时间(过时的)

date.setYear(year); // 设置年份
date.setMonth(month); // 设置月份
date.setDate(day); // 设置天数
date.setHours(hours); // 设置小时
date.setMinutes(minutes); // 设置分钟
date.setSeconds(seconds); // 设置秒钟

格式化和解析时间对象(部分过时)

SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 生成规定格式的时间对象(过时的)
String formattedDate = formatter.format(date); // 格式化Date对象为指定格式的字符串
Date parsedDate = formatter.parse("2022-01-01 12:00:00"); // 将字符串解析为Date对象

after Java 1.8


相关文章
|
7天前
|
SQL Java API
使用Java Stream API简化集合操作
使用Java Stream API简化集合操作
|
6天前
|
负载均衡 安全 Java
Java中的服务治理与API网关实现
Java中的服务治理与API网关实现
|
6天前
|
监控 安全 Java
在Java中集成第三方API调用的最佳实践
在Java中集成第三方API调用的最佳实践
|
7天前
|
Java API
如何利用Java Stream API简化集合操作?
如何利用Java Stream API简化集合操作?
|
10天前
|
开发框架 Java API
Java中的REST API开发详解
Java中的REST API开发详解
|
4天前
|
并行计算 Java 数据挖掘
Java面试题:解释Java中的Stream API及其操作
Java面试题:解释Java中的Stream API及其操作
10 0
|
6天前
|
安全 Java API
Java基础之新日期和时间
“【7月更文挑战第6天】”Java 8 引入了`java.time`包,改进了日期和时间处理。新API包括:`LocalDate`(线程安全的日期)、`LocalTime`(时间)、`LocalDateTime`(日期和时间)、`ZonedDateTime`(带时区的日期和时间)、`Instant`(时间戳)、`DateTimeFormatter`(线程安全的格式化器)、`Period`(日期间隔)和`Duration`(时间间隔)。
12 0
|
7天前
|
Java API
如何利用Java Stream API简化集合操作?
如何利用Java Stream API简化集合操作?
|
10天前
|
安全 Java API
Java基础之新日期和时间
“【7月更文挑战第5天】”Java 8 引入了`java.time`包,改进了日期和时间处理。新API包括线程安全的`LocalDate`、`LocalTime`、`LocalDateTime`、`ZonedDateTime`、`Instant`,以及`DateTimeFormatter`、`Period`和`Duration`。
14 0
|
4天前
|
Java 调度
Java线程的六种状态
Java线程有六种状态: 初始(NEW)、运行(RUNNABLE)、阻塞(BLOCKED)、等待(WAITING)、超时等待(TIMED_WAITING)、终止(TERMINATED)。
13 1