【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


相关文章
|
4天前
|
设计模式 Java API
Java 可扩展 API 设计:打造灵活的应用架构
【4月更文挑战第27天】设计可扩展的 API 是构建灵活、易于维护的应用程序架构的关键。Java 提供了丰富的工具和技术来实现这一目标,使开发者能够构建具有高度可扩展性的应用程序。
22 4
|
21小时前
|
分布式计算 Java API
Java 8新特性之Lambda表达式与Stream API
【5月更文挑战第1天】本文将介绍Java 8中的两个重要特性:Lambda表达式和Stream API。Lambda表达式是一种新的函数式编程语法,可以简化代码并提高可读性。Stream API是一种用于处理集合的新工具,可以方便地进行数据操作和转换。通过结合Lambda表达式和Stream API,我们可以更加简洁高效地编写Java代码。
|
2天前
|
NoSQL Java 关系型数据库
Java基础教程(21)-Java连接MongoDB
【4月更文挑战第21天】MongoDB是开源的NoSQL数据库,强调高性能和灵活性。Java应用通过MongoDB Java驱动与之交互,涉及MongoClient、MongoDatabase、MongoCollection和Document等组件。连接MongoDB的步骤包括:配置连接字符串、创建MongoClient、选择数据库和集合。伪代码示例展示了如何建立连接、插入和查询数据。
|
2天前
|
存储 Java 程序员
JAVA基本语法
JAVA基本语法
10 1
|
3天前
|
Java 关系型数据库 MySQL
Java基础教程(20)-Java连接mysql数据库CURD
【4月更文挑战第19天】MySQL是流行的关系型数据库管理系统,支持SQL语法。在IDEA中加载jar包到项目类路径:右击项目,选择“Open Module Settings”,添加库文件。使用JDBC连接MySQL,首先下载JDBC驱动,然后通过`Class.forName()`加载驱动,`DriverManager.getConnection()`建立连接。执行CRUD操作,例如创建表、插入数据和查询,使用`Statement`或`PreparedStatement`,并确保正确关闭数据库资源。
|
5天前
|
Java API 开发者
【专栏】Java 8新特性之Stream API详解
【4月更文挑战第27天】Java 8的Stream API是处理集合数据的新方式,强调简洁和声明式编程。它基于延迟执行和惰性求值,提供创建、中间操作(如filter、map)和终端操作(如forEach、collect)。示例展示了如何通过Stream排序、过滤、映射和聚合数据。
|
5天前
|
安全 Java
【JAVA】Java8开始ConcurrentHashMap,为什么舍弃分段锁
【JAVA】Java8开始ConcurrentHashMap,为什么舍弃分段锁
|
5天前
|
网络协议 Java 网络架构
Java基础教程(18)-Java中的网络编程
【4月更文挑战第18天】Java网络编程简化了底层协议处理,利用Java标准库接口进行TCP/IP通信。TCP协议提供可靠传输,常用于HTTP、SMTP等协议;UDP协议则更高效但不保证可靠性。在TCP编程中,ServerSocket用于监听客户端连接,Socket实现双进程间通信。UDP编程中,DatagramSocket处理无连接的数据报文。HTTP编程可以通过HttpURLConnection发送请求并接收响应。
|
6天前
|
Java 编译器 API
Java基础教程(17)-Java8中的lambda表达式和Stream、Optional
【4月更文挑战第17天】Lambda表达式是Java 8引入的函数式编程特性,允许函数作为参数或返回值。它有简洁的语法:`(parameters) -> expression 或 (parameters) ->{ statements; }`。FunctionalInterface注解用于标记单方法接口,可以用Lambda替换。
|
6天前
|
存储 SQL Java
Java8 Stream API 详解:流式编程进行数据处理
Java8 Stream API 详解:流式编程进行数据处理