包装类
包装类的默认值是null
装箱和拆箱(自动装箱和拆箱)
包装类 | 基本数据类型 |
---|---|
Byte | byte |
Short | short |
Integer | int |
Long | long |
Float | float |
Double | double |
Character | char |
Boolean | boolean |
Q:Integer不能引用传递?
A:是的,Integer 类中final的value字段,说明一旦integer类创建之后他的值就不能被修改,在 index++ 的时候Integer是创建一个新的类
public final class Integer extends Number implements Comparable<Integer> {
//...
private final int value;
//...
public Integer(int value) {
this.value = value;
}
//...
}
Integer 缓冲区(-128~127)
public static void main(String[] args) {
Integer i1 = new Integer(100);
Integer i2 = new Integer(100);
System.out.println(i1 == i2);
Integer i3 = Integer.valueOf(100);
Integer i4 = Integer.valueOf(100);
System.out.println(i3 == i4);
//Integer i5 = 200 等价于 Integer i5 = Integer.valueOf(200) 自动装箱
//缓冲了-128~127
Integer i5 = Integer.valueOf(128);
Integer i6 = Integer.valueOf(128);
System.out.println(i5 == i6);
}
输出
false
true
false
Integer.valueOf源码
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
Q:基本类型可以分配在栈上,也可以分配在堆上,这是为什么?
A: 原因
Math类
public static void main(String[] args) {
System.out.println("90度的正弦值:" + Math.sin(Math.PI / 2));
System.out.println("2的平方根与2商的反弦值:" + Math.asin(Math.sqrt(2)/2));
System.out.println("e的平方值:"+ Math.exp(2));
System.out.println("以e为底2的对数值:" + Math.log(2));
System.out.println("以10为底2的对数值:" + Math.log10(2));
System.out.println("2的平方根:" + Math.sqrt(2));
System.out.println("2的平方:" + Math.pow(2,2));
System.out.println("不小于3.5的最小整数" + Math.ceil(3.5));
System.out.println("不大于3.5的最大整数:" + Math.floor(3.5));
System.out.println("3.5最接近的整数为,同样接近取偶数:" + Math.rint(3.5));
}
输出
90度的正弦值:1.0
2的平方根与2商的反弦值:0.7853981633974484
e的平方值:7.38905609893065
以e为底2的对数值:0.6931471805599453
以10为底2的对数值:0.3010299956639812
2的平方根:1.4142135623730951
2的平方:4.0
不小于3.5的最小整数4.0
不大于3.5的最大整数:3.0
3.5最接近的整数为,同样接近取偶数:4.0
随机数
**Math.random()**方法返回一个大于等于0,小于1的随机数。该方法返回的随机数实际上是伪随机数
Random类
Random类中实现的随机算法是伪随机,也就是有规则的随机。
在进行随机时,随机算法的起源数字称为种子数(seed),在种子数的技术上进行一定的变换,从而产生需要的数字。
(Q:seed有什么作用?
A:seed 是 Random 生成随机数时使用的参数
public static void main(String[] args) {
System.out.println("有参构造");
Random random = new Random(10);
for (int i = 0; i < 10; i++) {
System.out.print(random.nextInt(100) + "\t");
}
System.out.println("\n无参构造");
Random random1 = new Random();
for (int i = 0; i < 10; i++) {
System.out.print(random1.nextInt(100) + "\t");
}
}
运行结果
//第一次执行
有参构造
13 80 93 90 46 56 97 88 81 14
无参构造
63 52 27 91 60 20 97 68 4 61
//第二次执行
有参构造
13 80 93 90 46 56 97 88 81 14
无参构造
51 13 3 78 37 1 71 3 7 58
总结
- 随机数是种子经过计算生成的
- 不含参的构造函数每次都使用当前时间作为种子,随机性更强
- 而含参的构造函数其实是伪随机,更有可预见性
)
为了避免两个Random对象产生同样的数字序列,我们可以使用当前时间作为种子Random r=new Random(System.currentTimeMillis());
相同种子数的Random对象,相同次数生成的随机数字是完全相同的。
无参构造方法
public Random() {
this(seedUniquifier() ^ System.nanoTime());
}
有参构造方法
public Random(long seed) {
if (getClass() == Random.class)
this.seed = new AtomicLong(initialScramble(seed));
else {
// subclass might have overriden setSeed
this.seed = new AtomicLong();
setSeed(seed);
}
}
第一个构造方法使用一个和当前系统时间对应的相对时间有关的数字作为种子数,然后使用这个种子数构造Random对象。
第二个构造方法可以通过制定一个种子数进行创建。
方法
boolean nextBoolean(); //返回下一个伪随机数,它是取自此随机数生成器序列的均匀分布的boolean值。
double nextDouble(); //返回下一个伪随机数,它是取自此随机数生成器序列的,在0.0和1.0之间均匀分布的double值
float nextFloat(); //返回下一个伪随机数,它是取自此随机数生成器序列的、在0.0和1.0之间均匀分布float值。
int nextInt(); //返回下一个伪随机数,它是此随机数生成器的序列中均匀分布的 int 值。
int nextInt(int n); //返回一个伪随机数,它是取自此随机数生成器序列的、在(包括和指定值(不包括)之间均匀分布的int值。
long nextLong(); //返回下一个伪随机数,它是取自此随机数生成器序列的均匀分布的 long 值。
public static void main(String[] args) {
System.out.println("-------模拟微信抢红包-------");
Random r = new Random();
Scanner sc = new Scanner(System.in);
System.out.println("请输入红包金额:");
double total = sc.nextDouble();
System.out.println("请输入红包总数:");
int bagsnum = sc.nextInt();
double min = 0.01;
for (int i = 1; i < bagsnum; i++) {
double max = total - (bagsnum - i) * min;
double bound = max - min;
double safe = (double) r.nextInt((int) (bound * 100)) / 100;
double money = safe + min;
total = total - money;
System.out.println("第" + i + "个红包的金额是:" + String.format("%.2f", money));
}
System.out.println("第" + bagsnum + "个红包的金额是:" + String.format("%.2f", total));
sc.close();
}
验证
-------模拟微信抢红包-------
请输入红包金额:
10
请输入红包总数:
10
第1个红包的金额是:9.06
第2个红包的金额是:0.71
第3个红包的金额是:0.05
第4个红包的金额是:0.07
第5个红包的金额是:0.01
第6个红包的金额是:0.01
第7个红包的金额是:0.03
第8个红包的金额是:0.02
第9个红包的金额是:0.01
第10个红包的金额是:0.03
日期时间类
Date类
DataFormat类
Calendar类
推荐:LocalDate、LocalDateTime
BigDecimal类
public static void main(String[] args) {
//不要用浮点数做运算,不精确
System.out.println(1.0 - 0.9);
System.out.println(add(0.1, 0.4));
System.out.println(subtract(1.0, 0.9));
System.out.println(divide(4.0, 0.1));
System.out.println(divide(20, 3));
}
public static double add(double d1, double d2) {
BigDecimal b1 = new BigDecimal(Double.toString(d1));
BigDecimal b2 = new BigDecimal(Double.toString(d2));
return b1.add(b2).doubleValue();
}
public static double subtract(double d1, double d2) {
BigDecimal b1 = new BigDecimal(Double.toString(d1));
BigDecimal b2 = new BigDecimal(Double.toString(d2));
return b1.subtract(b2).doubleValue();
}
public static double multiply(double d1, double d2) {
BigDecimal b1 = new BigDecimal(Double.toString(d1));
BigDecimal b2 = new BigDecimal(Double.toString(d2));
return b1.multiply(b2).doubleValue();
}
public static double divide(double d1, double d2) {
BigDecimal b1 = new BigDecimal(Double.toString(d1));
BigDecimal b2 = new BigDecimal(Double.toString(d2));
return b1.divide(b2,2,BigDecimal.ROUND_HALF_UP).doubleValue();
}
输出:
0.09999999999999998
0.5
0.1
40.0
6.67
DecimalFormat类
public class TestNumberFormat {
public static void main(String[] args) {
//圆周率
double pi = 3.1415927;
//取一位整数
System.out.println(new DecimalFormat("0").format(pi));//3
//取一位整数和两位小数
System.out.println(new DecimalFormat("0.00").format(pi));//3.14
//取两位整数和三位小数,整数不足部分以0填补。
System.out.println(new DecimalFormat("00.000").format(pi));//03.142
//取所有整数部分
System.out.println(new DecimalFormat("#").format(pi));//3
//以百分比方式计数,并取两位小数
System.out.println(new DecimalFormat("#.##%").format(pi));//314.16%
//光速
long c = 299792458;
//显示为科学计数法,并取五位小数
System.out.println(new DecimalFormat("#.#####E0").format(c));//2.99792E8
//显示为两位整数的科学计数法,并取四位小数
System.out.println(new DecimalFormat("00.####E0").format(c));//29.9792E7
//每三位以逗号进行分隔。
System.out.println(new DecimalFormat(",###").format(c));//299,792,458
//将格式嵌入文本
System.out.println(new DecimalFormat("光速大小为每秒,###米。").format(c));//光速大小为每秒299,792,458米。
System.out.println(new DecimalFormat("0.00").format(3.1));//3.10
System.out.println(new DecimalFormat("#.###").format(3.1025));//3.103
}
}
StringBuffer、StringBuilder、String
String常用方法
- char charAt(int index) – 返回指定索引处的 char 值
- String concat(String str) – 将指定字符串连接到此字符串的结尾
- boolean endWith(String suffix) – 此字符串是否以指定的后缀结束
- boolean equals(Object anObject) – 用于比较两个字符串的内容是否相等
- byte[] getBytes() – 使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中
- byte[] getByte(String charsetName) – 使用指定的字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中
- int hashCode() – 返回此字符串的哈希码
- int indexOf(String str) – 返回指定字符在字符串中第一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1
- int index(String str, int fromIndex) – 返回从 fromIndex 位置开始查找指定字符在字符串中第一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1
- length()
- charAt(int)
拓展
使用 == 和 equals() 比较字符串。
String 中 == 比较引用地址是否相同,equals() 比较字符串的内容是否相同(和Object的equals不一样!):
String s1 = "Hello"; // String 直接创建
String s2 = "Hello"; // String 直接创建
String s3 = s1; // 相同引用
String s4 = new String("Hello"); // String 对象创建
String s5 = new String("Hello"); // String 对象创建
s1 == s1; // true, 相同引用
s1 == s2; // true, s1 和 s2 都在公共池中,引用相同
s1 == s3; // true, s3 与 s1 引用相同
s1 == s4; // false, 不同引用地址
s4 == s5; // false, 堆中不同引用地址
s1.equals(s3); // true, 相同内容
s1.equals(s4); // true, 相同内容
s4.equals(s5); // true, 相同内容
String 是final类
String对象一旦创建之后该对象是不可更改的
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
}
String str = "ABC";
System.out.println(str);
str = str + "DEF";
System.out.println(str);
如果运行这段代码会发现先输出“ABC”,然后又输出“ABCDEF”,好像是str这个对象被更改了,其实,这只是一种假象罢了,JVM对于这几行代码是这样处理的,首先创建一个String对象str,并把“ABC”赋值给str,然后在第三行中,其实JVM又创建了一个新的对象也名为str,然后再把原来的str的值和“DEF”加起来再赋值给新的str,而原来的str就会被JVM的垃圾回收机制(GC)给回收掉了,所以,str实际上并没有被更改,也就是前面说的String对象一旦创建之后就不可更改了。所以,**Java中对String对象进行的操作实际上是一个不断创建新的对象并且将旧的对象回收的一个过程,所以执行速度很慢。**而StringBuilder和StringBuffer的对象是变量,对变量进行操作就是直接对该对象进行更改,而不进行创建和回收的操作,所以速度要比String快很多。
StringBuilder是线程不安全的,而StringBuffer是线程安全的(synchronized)
String:适用于少量的字符串操作的情况
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况
public static void main(String[] args) {
long start = System.currentTimeMillis();
String str = "";
for (int i = 0; i < 50000; i++) {
str += i;
}
long end = System.currentTimeMillis();
System.out.println("String耗时:" + (end - start) + "毫秒");
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 50000; i++) {
sb.append(i);
}
long end2 = System.currentTimeMillis();
System.out.println("StringBuffer耗时:" + (end2 - end) + "毫秒");
StringBuilder sb2 = new StringBuilder();
for (int i = 0; i < 50000; i++) {
sb2.append(i);
}
long end3 = System.currentTimeMillis();
System.out.println("StringBuilder耗时:" + (end3 - end2) + "毫秒");
}
输出
String耗时:4519毫秒
StringBuffer耗时:11毫秒
StringBuilder耗时:1毫秒
String 常用方法
public static void main(String[] args) {
String str = "努力学习java啊!努力努力啊!";
System.out.println(str.length());
System.out.println(str.charAt(0));
System.out.println(str.contains("java"));
System.out.println(str.contains("php"));
char[] chars = str.toCharArray();
System.out.println(Arrays.toString(chars));
System.out.println(str.indexOf("努力"));
System.out.println(str.indexOf("努力",10));
System.out.println(str.lastIndexOf("努力"));
System.out.println("==============");
String str2 = " java PHP css; ";
System.out.println(str2.trim());
System.out.println(str2.toUpperCase());
System.out.println(str2.toLowerCase());
System.out.println(str2.endsWith(" "));
System.out.println(str2.startsWith(" "));
System.out.println("==============");
String str3 = "java,php,css";
System.out.println(str3.replaceAll("css", "javaScript"));
System.out.println(Arrays.toString(str3.split(",")));
System.out.println("==============");
String str4 = "hello";
String str5 = "HELLO";
System.out.println(str4.equalsIgnoreCase(str5));
}
输出
16
努
true
false
[努, 力, 学, 习, j, a, v, a, 啊, !, 努, 力, 努, 力, 啊, !]
0
10
12
==============
java PHP css;
JAVA PHP CSS;
java php css;
true
true
==============
java,php,javaScript
[java, php, css]
==============
true
首字母转大写
public static void main(String[] args) {
String str = "i having study";
String[] s = str.split(" ");
String newStr = "";
for (int i = 0; i < s.length; i++) {
char[] chars = s[i].toCharArray();
chars[0] -= 32;
if (i == 0) {
newStr = String.valueOf(chars);
} else {
newStr = newStr + " " + String.valueOf(chars);
}
}
System.out.println(newStr);
}
输出
I Having Study
String.format()方法
转换符说明
转换符 | 说明 | 实例 |
---|---|---|
%s | 字符串类型 | “hello” |
%c | 字符类型 | ‘m’ |
%b | 布尔类型 | true |
%d | 整数类型(十进制) | 99 |
%x | 整数类型(十六进制) | FF |
%o | 整数类型(八进制) | 77 |
%f | 浮点类型 | 99.99 |
%a | 十六进制浮点数 | FF.35AE |
%e | 指数类型 | 9.38e+5 |
%g | 通用浮点类型(f和e类型中较短的) | |
%h | %h | |
%% | 百分比类型 | % |
%n | 换行符 |
public static void main(String[] args) {
String str = String.format("Hi,%s", "王力");//Hi,王力
System.out.println(str);
str = String.format("Hi,%s:%s.%s", "王南", "王力", "王张");//Hi,王南:王力.王张
System.out.println(str);
System.out.printf("字母a的大写是:%c %n", 'A');//字母a的大写是:A
System.out.printf("3>7的结果是:%b %n", 3 > 7);//3>7的结果是:false
System.out.printf("100的一半是:%d %n", 100 / 2);//100的一半是:50
System.out.printf("100的16进制数是:%x %n", 100);//100的16进制数是:64
System.out.printf("100的8进制数是:%o %n", 100);//100的8进制数是:144
System.out.printf("50元的书打8.5折扣是:%.2f 元%n", 50 * 0.85);//50元的书打8.5折扣是:42.50 元
System.out.printf("上面价格的16进制数是:%a %n", 50 * 0.85);//上面价格的16进制数是:0x1.54p5
System.out.printf("上面价格的指数表示:%e %n", 50 * 0.85);//上面价格的指数表示:4.250000e+01
System.out.printf("上面的折扣是%d%% %n", 85);//上面的折扣是85%
System.out.printf("字母A的散列码是:%h %n", 'A');//字母A的散列码是:41
}
Object类
方法
- public final native Class<?> getClass();
- public native int hashCode();
- public String toString();
- public boolean equals(Object obj); – 比较对象的引用对象是否是同一个
- protected void finalize() throws Throwable { } – 当对象呗判断为垃圾对象时,由JVM自动调用此方法,用以标记垃圾对象,进入回收队列。
public class Student {
private String name;
private int age;
Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
public static void main(String[] args) {
System.out.println("=====getClass=====");
Student student1 = new Student("张三", 12);
Student student2 = new Student("李四", 12);
System.out.println(student1.getClass() == student2.getClass());
System.out.println("=====hashCode=====");
System.out.println(student1.hashCode());
System.out.println(student2.hashCode());
Student student3 = student1;
System.out.println(student3.hashCode());
System.out.println("=====toString(重写之后)=====");
System.out.println(student1.toString());
Student student4 = new Student("张三", 13);
Student student5 = new Student("张三", 13);
System.out.println("=====equals(重写之后)=====");
System.out.println(student4.equals(student5));
System.out.println(student4.hashCode());
System.out.println(student5.hashCode());
}
输出
=====getClass=====
true
=====hashCode=====
24022532
26104864
24022532
=====toString(重写之后)=====
Student{name='张三', age=12}
=====equals(重写之后)=====
true
24022533
24022533
finalize() 案例
public class Student {
private String name;
private int age;
Student(String name, int age) {
this.age = age;
this.name = name;
}
@Override
protected void finalize() throws Throwable {
System.out.println(this.name+"被垃圾回收了");
}
}
public static void main(String[] args) {
Student s1 = new Student("A", 12);
Student s2 = new Student("B", 12);
Student s3 = new Student("C", 12);
System.out.println("========");
new Student("D", 12);
new Student("E", 12);
new Student("F", 12);
//手动回收机制,通知JVM执行垃圾回收
System.gc();
System.out.println("垃圾回收完成!");
}
输出
========
垃圾回收完成!
F被垃圾回收了
E被垃圾回收了
D被垃圾回收了
Q:重写equal为啥要重写hashCode
A: 原因
哈希值根据根据对象的地址或者字符串或者数字使用hash算法计算出来的int类型的数值。
拓展:Objects.equals(obj1, obj2)
public static void main(String[] args) {
String str1 = "查煜垚";
String str2 = "查煜垚";
System.out.println(Objects.equals(str1, str2));//true
System.out.println(str1 == str2);//true
System.out.println("==========");
String str3 = "查煜垚";
String str4 = new String("查煜垚");
System.out.println(str3.hashCode());//26481763
System.out.println(str4.hashCode());//26481763
System.out.println(Objects.equals(str3, str4));//true
System.out.println(str3.equals(str4));//true
System.out.println(str3 == str4);//false
System.out.println("==========");
Object obj1 = "查煜垚";
Object obj2 = new String("查煜垚");
System.out.println(obj1.hashCode());//26481763
System.out.println(obj2.hashCode());//26481763
System.out.println(Objects.equals(obj1, obj2));//true
System.out.println(obj1 == obj2);//false
}
System类
//方法一:数组复制
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
//方法二:系统当前毫秒数
public static native long currentTimeMillis();
//方法三:垃圾回收
public static void gc() {
Runtime.getRuntime().gc();
}
//方法四:退出jvm
public static void exit(int status) {
Runtime.getRuntime().exit(status);
}
File类
public static void main(String[] args) {
File file = new File("C:\\Users\\ZHAYUYAO\\Desktop\\爸妈手机考虑.xlsx");
System.out.println("===isFile()==="+file.isFile());
System.out.println("===getName()==="+file.getName());
System.out.println("===getPath()==="+file.getPath());
System.out.println("===getParent()==="+file.getParent());
System.out.println("===isAbsolute()==="+file.isAbsolute());
System.out.println("===exists()==="+file.exists());
System.out.println("===length()==="+(file.length()));
//public boolean mkdir() 创建此抽象路径名指定的目录
//public boolean mkdirs() 创建此抽象路径名指定的目录,包括创建必需但不存在的父目录
}
输出
===isFile()===true
===getName()===爸妈手机考虑.xlsx
===getPath()===C:\Users\ZHAYUYAO\Desktop\爸妈手机考虑.xlsx
===getParent()===C:\Users\ZHAYUYAO\Desktop
===isAbsolute()===true
===exists()===true
===length()===10221
FileFilter接口
递归
- 遍历
- 删除
public static void main(String[] args) {
// listFile(new File("D:\\test"));
delete(new File("D:\\test"));
}
public static void listFile(File dir) {
File[] files = dir.listFiles();
for (File file : files) {
if (file.isDirectory()) {
//递归
listFile(file);
} else {
System.out.println(file.getAbsolutePath());
}
}
System.out.println(dir.getAbsolutePath());
}
public static void delete(File dir) {
File[] files = dir.listFiles();
for (File file : files) {
if (file.isDirectory()) {
//递归
delete(file);
} else {
System.out.println("删除:" + file.getAbsolutePath() + ":" + file.delete());
}
}
System.out.println("删除:" + dir.getAbsolutePath() + ":" + dir.delete());
}