JDK API 1.8 中文版 jdk api 1.8.CHM
内置数据类型对应的包装类Number
一般地,当需要使用数字的时候,我们通常使用内置数据类型,如:byte、int、long、double 等。然而,在实际开发过程中,我们经常会遇到需要使用对象,而不是内置数据类型的情形。为了解决这个问题,Java 语言为每一个内置数据类型提供了对应的包装类。
所有的包装类(Integer、Long、Byte、Double、Float、Short)都是抽象类 Number 的子类。
这种由编译器特别支持的包装称为装箱,所以当内置数据类型被当作对象使用的时候,编译器会把内置类型装箱为包装类。相似的,编译器也可以把一个对象拆箱为内置类型。Number 类属于 java.lang 包。
public class Test{
public static void main(String args[]){
Integer x = 5;
x = x + 10;
System.out.println(x);
}
}
当 x 被赋为整型值时,由于x是一个对象,所以编译器要对x进行装箱。然后,为了使x能进行加运算,所以要对x进行拆箱。
简单一点说,装箱就是自动将基本数据类型转换为包装器类型;拆箱就是自动将包装器类型转换为基本数据类型。
(1)Java 会对 -128 ~ 127 的整数进行缓存,所以当定义两个变量初始化值位于 -128 ~ 127 之间时,两个变量使用了同一地址:
Integer a=123;
Integer b=123;
System.out.println(a==b); // 输出 true
System.out.println(a.equals(b)); // 输出 true
//当两个 Integer 变量的数值超出 -128 ~ 127 范围时, 变量使用了不同地址:
a=1230;
b=1230;
System.out.println(a==b); // 输出 false
System.out.println(a.equals(b)); // 输出 true
Java 中 int 和 Integer 的区别
1. int 是基本数据类型,int 变量存储的是数值。Integer 是引用类型,实际是一个对象,Integer 存储的是引用对象的地址。**
Integer i = new Integer(100);
Integer j = new Integer(100);
System.out.print(i == j); //false
因为 new 生成的是两个对象,其内存地址不同。
2.**int 和 Integer 所占内存比较:
Integer 对象会占用更多的内存。Integer 是一个对象,需要存储对象的元数据。但是 int 是一个原始类型的数据,所以占用的空间更少。
3. 非 new 生成的 Integer 变量与 new Integer() 生成的变量比较,结果为 false。
/**
* 比较非new生成的Integer变量与new生成的Integer变量
*/
public class Test {
public static void main(String[] args) {
Integer i= new Integer(200);
Integer j = 200;
System.out.print(i == j);
//输出:false
}
}
因为非 new 生成的 Integer 变量指向的是 java 常量池中的对象,而 new Integer() 生成的变量指向堆中新建的对象,两者在内存中的地址不同。所以输出为 false。
4. 两个非 new 生成的 Integer 对象进行比较,如果两个变量的值在区间 [-128,127]** 之间,比较结果为 true;否则,结果为 false。
/**
* 比较两个非new生成的Integer变量
*/
public class Test {
public static void main(String[] args) {
Integer i1 = 127;
Integer ji = 127;
System.out.println(i1 == ji);//输出:true
Integer i2 = 128;
Integer j2 = 128;
System.out.println(i2 == j2);//输出:false
}
}
java 在编译 Integer i1 = 127 时,会翻译成 Integer i1 = Integer.valueOf(127)。
5.** Integer 变量(无论是否是 new 生成的)与 int 变量比较,只要两个变量的值是相等的,结果都为 true。
/**
* 比较Integer变量与int变量
*/
public class Test {
public static void main(String[] args) {
Integer i1 = 200;
Integer i2 = new Integer(200);
int j = 200;
System.out.println(i1 == j);//输出:true
System.out.println(i2 == j);//输出:true
}
}
包装类 Integer 变量在与基本数据类型 int 变量比较时,Integer 会自动拆包装为 int,然后进行比较,实际上就是两个 int 变量进行比较,值相等,所以为 true。
Math
Math 的方法都被定义为 static 形式,通过 Math 类可以在主函数中直接调用。
常用函数
巧记对floor()和ceil()的概念理解:
1. floor直接取其含义,也就是“地板”,地板在脚下,即向下取整。
2. ceil是ceiling的缩写,也就是“天花板”,天花板在头顶上,即向上取整。
这里需要注意,floor()和ceil()的返回值都是double类型的数值。
round()的四舍五入也可以引入y轴来确定:
不管正数还是负数,四舍五入法要求,凡是.5的小数,都要向上取整。
因此,负数.5小数的四舍五入,只需直接取绝对值,再加上负号,就完成了。
随机数
除了Math.random()获取0~1之间的随机数, 还有 java.util.Random 类。
// 实例化随机数
Random r = new Random();
// 得到0-7之间的随机数
int num = r.nextInt(8);
// 如果想得到 0-8 之间的随机数
int num = r.nextInt(9);
// 如果想得到50-100之间的随机数
int num = r.nextInt(51)+50;
// 这个 51 = 100 - 50 + 1
java.util.Random 类
String
常用方法:
取出字符串中的一个字 charAt()
String message = "Hello Java";
// 取出第一个字
char str = message.charAt(0);
去除多余空格 trim()
- 查找字符串 indexOf()
- 字符串拼接 substring()
- 字符串开始和结束内容判断 startsWith / endsWith
```java
if(fileName.endsWith(“.doc”)){
}System.out.println("是word文档");
if(url.startsWith(“https”)){ System.out.println(“网址是安全的”); }
- 字符串替换 replaceAll()
```java
String str = "Java是一种广泛使用的计算机编程语言,拥有跨平台、面向对象、泛型编程的特性,广泛应用于企业级Web应用开发和移动应用开发。于1995年5月以Java的名称正式发布。Java伴随着互联网的迅猛发展而发展,逐渐成为重要的网络编程语言。";
String newStr = str.replaceAll("Java","Python");//前旧值,后新值
关于 为啥是不可改变的
String s = "Google";
System.out.println("s = " + s);
s = "Runoob";
System.out.println("s = " + s);
//输出结果
Runoob
从结果上看是改变了,但为什么门说String对象是不可变的呢?
原因在于实例中的 s 只是一个 String 对象的引用,并不是对象本身,当执行 s = “Runoob”; 创建了一个新的对象 “Runoob”,而原来的 “Google” 还存在于内存中。
这里可以根据 jdk 的源码来分析。
字符串实际上就是一个 char 数组,并且内部就是封装了一个 char 数组。
并且这里 char 数组是被 final 修饰的:
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
并且 String 中的所有的方法,都是对于 char 数组的改变,只要是对它的改变,方法内部都是返回一个新的 String 实例。
String 类的常见面试问题
面试题一:
String s1 = "abc"; // 常量池
String s2 = new String("abc"); // 堆内存中
System.out.println(s1==s2); // false两个对象的地址值不一样。
System.out.println(s1.equals(s2)); // true
面试题二:
String s1="a"+"b"+"c";
String s2="abc";
System.out.println(s1==s2);
System.out.println(s1.equals(s2));
java 中常量优化机制,编译时 s1 已经成为 abc 在常量池中查找创建,s2 不需要再创建。
面试题三:
String s1="ab";
String s2="abc";
String s3=s1+"c";
System.out.println(s3==s2); // false
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 来创建对象,创建出的一定是不同的对象,即使字符串的内容是相同的。
时间日期类
转化
日期时间——>字符串的转化:
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class DateTest5 {
public static void main(String[] args) {
LocalDate time = LocalDate.now();
// 打印默认的时间数据
System.out.println(time.toString());
// 创建一个格式化方式
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy年MM月dd");
// 或者利用SimpleDateFormat类
// SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd hh:mm:ss");
// 执行时间的格式化处理,得到期望格式的时间字符串
String timeStr = df.format(time);
// 打印时间
System.out.println(timeStr);
}
}
字符串——>日期时间:
import java.time.LocalDate;
public class DateTest {
public static void main(String[] args) {
// 定义一个时间字符串,日期是2019年1月1日
//默认格式yyyy-MM-dd
String date = "2019-01-01";
// 把字符串转化位 LocalDate 对象,并得到字符串匹配的日期
LocalDate date2 = LocalDate.parse(date);
// 打印出日期
System.out.println(date2.toString());
}
}
自定义格式
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class DateTest {
public static void main(String[] args) {
// 定义一个时间字符串,日期是2019年1月1日
String date = "2019/01/01";
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy/MM/dd");
// 把字符串转化位 LocalDate 对象,并得到字符串匹配的日期
LocalDate date2 = LocalDate.parse(date,df);
// 打印出日期
System.out.println(date2.toString());
}
}
获取日期时间具体的值:
import java.time.LocalDate;
public class DateTest7 {
public static void main(String[] args) {
LocalDate time = LocalDate.now();
// 得到当前时间所在年
int year = time.getYear();
System.out.println("当前年份 " + year);
// 得到当前时间所在月
int month = time.getMonth().getValue();
System.out.println("当前月份 " + month);
// 得到当前时间在这个月中的天数
int day = time.getDayOfMonth();
System.out.println("当前日 " + day);
// 得到当前时间所在星期数
int dayOfWeek = time.getDayOfWeek().getValue();
System.out.println("当前星期 " + dayOfWeek);
}
}
这里有的用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 类实现了这个接口。