JDK API 1.8 中文版 jdk api 1.8.CHM

内置数据类型对应的包装类Number

一般地,当需要使用数字的时候,我们通常使用内置数据类型,如:byte、int、long、double 等。然而,在实际开发过程中,我们经常会遇到需要使用对象,而不是内置数据类型的情形。为了解决这个问题,Java 语言为每一个内置数据类型提供了对应的包装类。
所有的包装类(Integer、Long、Byte、Double、Float、Short)都是抽象类 Number 的子类。
Java 常用内置类 - 图1
这种由编译器特别支持的包装称为装箱,所以当内置数据类型被当作对象使用的时候,编译器会把内置类型装箱为包装类。相似的,编译器也可以把一个对象拆箱为内置类型。Number 类属于 java.lang 包。

  1. public class Test{
  2. public static void main(String args[]){
  3. Integer x = 5;
  4. x = x + 10;
  5. System.out.println(x);
  6. }
  7. }

当 x 被赋为整型值时,由于x是一个对象,所以编译器要对x进行装箱。然后,为了使x能进行加运算,所以要对x进行拆箱。

简单一点说,装箱就是自动将基本数据类型转换为包装器类型;拆箱就是自动将包装器类型转换为基本数据类型。
(1)Java 会对 -128 ~ 127 的整数进行缓存,所以当定义两个变量初始化值位于 -128 ~ 127 之间时,两个变量使用了同一地址:

  1. Integer a=123;
  2. Integer b=123;
  3. System.out.println(a==b); // 输出 true
  4. System.out.println(a.equals(b)); // 输出 true
  5. //当两个 Integer 变量的数值超出 -128 ~ 127 范围时, 变量使用了不同地址:
  6. a=1230;
  7. b=1230;
  8. System.out.println(a==b); // 输出 false
  9. System.out.println(a.equals(b)); // 输出 true

Java 中 int 和 Integer 的区别

1. int 是基本数据类型,int 变量存储的是数值。Integer 是引用类型,实际是一个对象,Integer 存储的是引用对象的地址。**

  1. Integer i = new Integer(100);
  2. Integer j = new Integer(100);
  3. System.out.print(i == j); //false

因为 new 生成的是两个对象,其内存地址不同。

2.**int 和 Integer 所占内存比较:
Integer 对象会占用更多的内存。Integer 是一个对象,需要存储对象的元数据。但是 int 是一个原始类型的数据,所以占用的空间更少。

3. 非 new 生成的 Integer 变量与 new Integer() 生成的变量比较,结果为 false。

  1. /**
  2. * 比较非new生成的Integer变量与new生成的Integer变量
  3. */
  4. public class Test {
  5. public static void main(String[] args) {
  6. Integer i= new Integer(200);
  7. Integer j = 200;
  8. System.out.print(i == j);
  9. //输出:false
  10. }
  11. }

因为非 new 生成的 Integer 变量指向的是 java 常量池中的对象,而 new Integer() 生成的变量指向堆中新建的对象,两者在内存中的地址不同。所以输出为 false。

4. 两个非 new 生成的 Integer 对象进行比较,如果两个变量的值在区间 [-128,127]** 之间,比较结果为 true;否则,结果为 false。

  1. /**
  2. * 比较两个非new生成的Integer变量
  3. */
  4. public class Test {
  5. public static void main(String[] args) {
  6. Integer i1 = 127;
  7. Integer ji = 127;
  8. System.out.println(i1 == ji);//输出:true
  9. Integer i2 = 128;
  10. Integer j2 = 128;
  11. System.out.println(i2 == j2);//输出:false
  12. }
  13. }

java 在编译 Integer i1 = 127 时,会翻译成 Integer i1 = Integer.valueOf(127)

5.** Integer 变量(无论是否是 new 生成的)与 int 变量比较,只要两个变量的值是相等的,结果都为 true。

  1. /**
  2. * 比较Integer变量与int变量
  3. */
  4. public class Test {
  5. public static void main(String[] args) {
  6. Integer i1 = 200;
  7. Integer i2 = new Integer(200);
  8. int j = 200;
  9. System.out.println(i1 == j);//输出:true
  10. System.out.println(i2 == j);//输出:true
  11. }
  12. }

包装类 Integer 变量在与基本数据类型 int 变量比较时,Integer 会自动拆包装为 int,然后进行比较,实际上就是两个 int 变量进行比较,值相等,所以为 true。

Math

Math 的方法都被定义为 static 形式,通过 Math 类可以在主函数中直接调用。
常用函数
巧记对floor()ceil()的概念理解:
1. floor直接取其含义,也就是“地板”,地板在脚下,即向下取整
2. ceilceiling的缩写,也就是“天花板”,天花板在头顶上,即向上取整
这里需要注意,floor()和ceil()的返回值都是double类型的数值。
round()的四舍五入也可以引入y轴来确定:
不管正数还是负数,四舍五入法要求,凡是.5的小数,都要向上取整
因此,负数.5小数的四舍五入,只需直接取绝对值再加上负号,就完成了。

随机数

除了Math.random()获取0~1之间的随机数, 还有 java.util.Random 类。

  1. // 实例化随机数
  2. Random r = new Random();
  3. // 得到0-7之间的随机数
  4. int num = r.nextInt(8);
  5. // 如果想得到 0-8 之间的随机数
  6. int num = r.nextInt(9);
  7. // 如果想得到50-100之间的随机数
  8. int num = r.nextInt(51)+50;
  9. // 这个 51 = 100 - 50 + 1

java.util.Random 类

String

常用方法:

  • 取出字符串中的一个字 charAt()

    1. String message = "Hello Java";
    2. // 取出第一个字
    3. char str = message.charAt(0);
  • 去除多余空格 trim()

  • 查找字符串 indexOf()
  • 字符串拼接 substring()
  • 字符串开始和结束内容判断 startsWith / endsWith ```java if(fileName.endsWith(“.doc”)){
    1. System.out.println("是word文档");
    }

if(url.startsWith(“https”)){ System.out.println(“网址是安全的”); }

  1. - 字符串替换 replaceAll()
  2. ```java
  3. String str = "Java是一种广泛使用的计算机编程语言,拥有跨平台、面向对象、泛型编程的特性,广泛应用于企业级Web应用开发和移动应用开发。于1995年5月以Java的名称正式发布。Java伴随着互联网的迅猛发展而发展,逐渐成为重要的网络编程语言。";
  4. String newStr = str.replaceAll("Java","Python");//前旧值,后新值

关于 为啥是不可改变的

  1. String s = "Google";
  2. System.out.println("s = " + s);
  3. s = "Runoob";
  4. System.out.println("s = " + s);
  5. //输出结果
  6. Google
  7. Runoob

从结果上看是改变了,但为什么门说String对象是不可变的呢?
原因在于实例中的 s 只是一个 String 对象的引用,并不是对象本身,当执行 s = “Runoob”; 创建了一个新的对象 “Runoob”,而原来的 “Google” 还存在于内存中。
Java 常用内置类 - 图2
这里可以根据 jdk 的源码来分析。
字符串实际上就是一个 char 数组,并且内部就是封装了一个 char 数组。
并且这里 char 数组是被 final 修饰的:

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

并且 String 中的所有的方法,都是对于 char 数组的改变,只要是对它的改变,方法内部都是返回一个新的 String 实例。

String 类的常见面试问题

面试题一:

  1. String s1 = "abc"; // 常量池
  2. String s2 = new String("abc"); // 堆内存中
  3. System.out.println(s1==s2); // false两个对象的地址值不一样。
  4. System.out.println(s1.equals(s2)); // true

面试题二:

  1. String s1="a"+"b"+"c";
  2. String s2="abc";
  3. System.out.println(s1==s2);
  4. System.out.println(s1.equals(s2));
  5. java 中常量优化机制,编译时 s1 已经成为 abc 在常量池中查找创建,s2 不需要再创建。

面试题三:

  1. String s1="ab";
  2. String s2="abc";
  3. String s3=s1+"c";
  4. System.out.println(s3==s2); // false
  5. System.out.println(s3.equals(s2)); // true

先在常量池中创建 ab ,地址指向 s1, 再创建 abc ,指向 s2。对于 s3,先创建StringBuilder(或 StringBuffer)对象,通过 append 连接得到 abc ,再调用 toString() 转换得到的地址指向 s3。故 (s3==s2)false

Java String、StringBuffer 和 StringBuilder 的区别

String:字符串常量,字符串长度不可变。Java中String 是immutable(不可变)的。用于存放字符的数组被声明为final的,因此只能赋值一次,不可再更改。
StringBuffer:字符串变量(Synchronized,即线程安全)。如果要频繁对字符串内容进行修改,出于效率考虑最好使用 StringBuffer,如果想转成 String 类型,可以调用 StringBuffer 的 toString() 方法。Java.lang.StringBuffer 线程安全的可变字符序列。在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。可将字符串缓冲区安全地用于多个线程。
StringBuilder:字符串变量(非线程安全)。在内部 StringBuilder 对象被当作是一个包含字符序列的变长数组。
基本原则:

  • 如果要操作少量的数据用 String ;
  • 单线程操作大量数据用StringBuilder ;
  • 多线程操作大量数据,用StringBuffer。

众所周知,通过 new 关键字来生成对象是在堆区进行的,而在堆区进行对象生成的过程是不会去检测该对象是否已经存在的。因此通过 new 来创建对象,创建出的一定是不同的对象,即使字符串的内容是相同的。

时间日期类

转化

日期时间——>字符串的转化:

  1. import java.time.LocalDate;
  2. import java.time.format.DateTimeFormatter;
  3. public class DateTest5 {
  4. public static void main(String[] args) {
  5. LocalDate time = LocalDate.now();
  6. // 打印默认的时间数据
  7. System.out.println(time.toString());
  8. // 创建一个格式化方式
  9. DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy年MM月dd");
  10. // 或者利用SimpleDateFormat类
  11. // SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd hh:mm:ss");
  12. // 执行时间的格式化处理,得到期望格式的时间字符串
  13. String timeStr = df.format(time);
  14. // 打印时间
  15. System.out.println(timeStr);
  16. }
  17. }

字符串——>日期时间:

  1. import java.time.LocalDate;
  2. public class DateTest {
  3. public static void main(String[] args) {
  4. // 定义一个时间字符串,日期是2019年1月1日
  5. //默认格式yyyy-MM-dd
  6. String date = "2019-01-01";
  7. // 把字符串转化位 LocalDate 对象,并得到字符串匹配的日期
  8. LocalDate date2 = LocalDate.parse(date);
  9. // 打印出日期
  10. System.out.println(date2.toString());
  11. }
  12. }

自定义格式

  1. import java.time.LocalDate;
  2. import java.time.format.DateTimeFormatter;
  3. public class DateTest {
  4. public static void main(String[] args) {
  5. // 定义一个时间字符串,日期是2019年1月1日
  6. String date = "2019/01/01";
  7. DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy/MM/dd");
  8. // 把字符串转化位 LocalDate 对象,并得到字符串匹配的日期
  9. LocalDate date2 = LocalDate.parse(date,df);
  10. // 打印出日期
  11. System.out.println(date2.toString());
  12. }
  13. }

获取日期时间具体的值:

  1. import java.time.LocalDate;
  2. public class DateTest7 {
  3. public static void main(String[] args) {
  4. LocalDate time = LocalDate.now();
  5. // 得到当前时间所在年
  6. int year = time.getYear();
  7. System.out.println("当前年份 " + year);
  8. // 得到当前时间所在月
  9. int month = time.getMonth().getValue();
  10. System.out.println("当前月份 " + month);
  11. // 得到当前时间在这个月中的天数
  12. int day = time.getDayOfMonth();
  13. System.out.println("当前日 " + day);
  14. // 得到当前时间所在星期数
  15. int dayOfWeek = time.getDayOfWeek().getValue();
  16. System.out.println("当前星期 " + dayOfWeek);
  17. }
  18. }

这里有的用getValue()有的没有,点击拓展

日期比较

Java使用以下三种方法来比较两个日期:

  • 使用 getTime() 方法获取两个日期(自1970年1月1日经历的毫秒数值),然后比较这两个值。
  • 使用方法 before(),after() 和 equals()。例如,一个月的12号比18号早,则 new Date(99, 2, 12).before(new Date (99, 2, 18)) 返回true。
  • 使用 compareTo() 方法,它是由 Comparable 接口定义的,Date 类实现了这个接口。