一.Object类
1.1 概念
Object 类
- 1、Object 是所有的类的超类、基类。位于继承树的最顶层。
- 2、任何一个没有显示定义extends父类的类。都直接继承Object,否则就是间接继承
- 3、任何一个类都可以享有Object提供的方法
- 4、Object类可以代表任何一个类(多态),可以作为方法的参数、方法的返回值
1.2Object中常用方法
1.2.1getClass方法
此方法用于返回该对象的真实类型(运行时的类型)
- public final Class<?> getClass()
//判断运行时d对象和c对象是否是同一个类型
Animal d = new Dog();
Animal c = new Cat();
//方式1:通过 instanceof 关键字判断
if((d instanceof Dog && c instanceof Dog) ||(d instanceof Cat && c instanceof Cat)) {
System.out.println("是同一个类型");
}else {
System.out.println("不是同一个类型");
}
//方式2:通过getClass方法 判断
if(d.getClass() == c.getClass()) {
System.out.println("是同一个类型");
}else {
System.out.println("不是同一个类型");
}
1.2.2 hashCode方法
public native int hashCode();
- 1、返回该对象的十进制的哈希吗值
- 2、hash值是由hash算法通过对象的地址、对象中的字符串、数字等,计算出来的
- 3、相同的对象应当返回相同的哈希吗值,不同的对象尽量返回不同的哈希码值
Student stu1 = new Student("zhangsan", 30);
Student stu2 = new Student("zhangsan", 30);
Student stu3 = stu1;
System.out.println(stu1.hashCode());
System.out.println(stu2.hashCode());
System.out.println(stu3.hashCode());
//hash突出
String str1 = "通话";
String str2 = "重地";
System.out.println(str1.hashCode());
System.out.println(str2.hashCode());
1.2.3 toString方法
返回对象的字符串表现形式
- 全限定名+@+十六进制的hash值(地址)
- 如果直接输出一个对象,那么默认会调用这个对象的toString方法,而toString方法是Object类提供的,返回的是“对象的地址”。但是我们一般输出对象希望输出的是对象的属性信息,所以可以重写父类的toString方法
@Override public String toString() { return "Student [name=" + name + ", age=" + age + "]"; }
1.2.4 equals方法
Object类的equals方法的作用是比较两个对象是否相等。比较的是内存地址。其底层代码的是==
如果不想比较内存地址,那么需要重写equals方法
Student stu1 = new Student("zhangsan", 30);
Student stu2 = new Student("zhangsan", 30);
//重写equals方法之前
System.out.println(stu1 == stu2); //false
System.out.println(stu1.equals(stu2));//false
//希望如果两个对象的属性一样,就认为两个对象是相同的对象
//重写equals方法之后
System.out.println(stu1 == stu2); //false
System.out.println(stu1.equals(stu2));//true
System.out.println(stu1.hashCode());
System.out.println(stu2.hashCode());
重写equals方法
public boolean equals(Object obj) {
//1、非空判断
if(obj == null) {
return false;
}
//2、如果当前对象与obj相等
if(this == obj) {
return true;
}
//3、判断obj是否属于Student类型
if(obj instanceof Student) {
Student stu = (Student)obj;
//4、判断属性
if(this.name.equals(stu.name) && this.age == stu.age) {
return true;
}
}
return false;
}
总结:== 和 equals的区别
- 两个东西都是用于比较的
- == 可以用于基本类型和引用类型
- ==在基本类型的比较中,比较的值是否相等,如果相等返回true,否则返回false
- ==在引用类型的比较中,比较的地址是否相等,如果相等返回true,否则返回false
- equals只能用于引用类型的比较
- equals方法是Object类提供的方法,其底层实现是==比较,所以在没有重写父类的equals方法时。比较的也是地址。如果希望两个对象的属性一样,就认为两个对象是相同的对象,那么需要重写equals方法,但是重写了equals的同时也需要重写hashcode方法,因为java中约定两个对象相等,那么两个对象的hash值也应该相等
1.2.5方法
当垃圾回收器回收垃圾对象的时候,自动调用
public class Test5 {
public static void main(String[] args) {
Person p = new Person();
//手动将对象标记为垃圾对象
p = null;
//触发垃圾回收器,回收垃圾对象
System.gc();
}
}
class Person{
@Override
protected void finalize() throws Throwable {
super.finalize();//不要删除
System.out.println("finalize方法执行了");
}
}
二、包装类
2.1 概念
为什么要有包装类
- 因为基本数据类型不具有方法和属性。而引用数据类型可以拥有属性和方法,使用更加的灵活
- 所以Java给8种基本数据类型提供对应8个包装类。包装类也就是引用数据类型
基本类型 | 包装类型 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
2.2 装箱和拆箱
装箱就是将基本类型转换成包装类
拆箱就是将包装类型转换成基本类型
jdk1.5 之前装箱和拆箱
//在jdk1.5之前 拆装箱的过程
byte b = 10;
//装箱
Byte b1 = Byte.valueOf(b);
System.out.println(b1);
//拆箱
byte b2 = b1.byteValue();
System.out.println(b2);
jdk1.5 之后的装箱和拆箱
//在jdk1.5之后 拆装箱的过程
int i = 10;
//装箱
Integer i1 = i;
System.out.println(i1);
//装箱
int i2 = i1;
System.out.println(i2);
2.3Number类
Byte、Short、Integer、Long、Float、Double六个子类
提供一组方法,用于将其中某一种类型转换成其他类型 xxxValue()方法
Integer a = 100;
Byte b = a.byteValue();
Short c = a.shortValue();
Long d = a.longValue();
Float e = a.floatValue();
Double f = a.doubleValue();
Integer g = a.intValue();
2.4 常用的包装类
Integer 、Double
2.4.1 定义方式
//Integer、Double的定义方式
Integer ii1 = new Integer(100);
//或者
Integer ii1 = 100;
Double dd1 = new Double(100.2);
//或者
Double dd1 = 100.2;
2.4.2 常用的属性
System.out.println(Integer.MAX_VALUE);
System.out.println(Integer.MIN_VALUE);
System.out.println(Double.MAX_VALUE);
System.out.println(Double.MIN_VALUE);
2.4.3 常用的方法
将字符串类型的数值转换成int或者是double类型
//常用方法:
//将字符串转换成int或者是double
String s = "123";
//方式1:
int i = Integer.parseInt(s);
System.out.println(i);
//方式2:
int i2 = Integer.valueOf(s);
System.out.println(i2);
String s1 = "20.5";
//方式1:
double d = Double.parseDouble(s1);
System.out.println(d);
//方式2:
double d1 = Double.valueOf(s1);
System.out.println(d1);
//java.lang.NumberFormatException 数字格式化异常
String s2 = null;
System.out.println(Integer.parseInt(s2));
2.5 缓冲区(面试题)
public class Demo02 {
public static void main(String[] args) {
/**
* 面试题:整数型包装类缓冲区
* 整数型的包装类定义缓冲区(-128~127),如果定义的数在这个范围你之内,那么直接从缓存数组中获取,
* 否则,重新new新的对象
*/
Integer i1 = new Integer(10);
Integer i2 = new Integer(10);
System.out.println(i1 == i2); //false
System.out.println(i1.equals(i2));//true
Integer i3 = 1000; //Integer i3 = new Integer(1000);
Integer i4 = 1000; //Integer i3 = new Integer(1000);
System.out.println(i3 == i4); //false
System.out.println(i3.equals(i4));//true
Integer i5 = 100; //IntegerCache.cache[i + (-IntegerCache.low)]
Integer i6 = 100; //IntegerCache.cache[i + (-IntegerCache.low)]
System.out.println(i5 == i6);//true
System.out.println(i5.equals(i6));//true
}
}
三、String类
3.1 概念
String
类代表字符串。 Java程序中的所有字符串文字(例如"abc"
)都被实现为此类的实例。String
字符串被创建就不能修改。
3.2 String创建对象
- 直接赋值
- 通过构造方法创建对象
//String类的定义
//1、直接赋值
String s = "cxk";
System.out.println(s);
//2、通过构造方法创建String类的对象
String s1 = new String("李四哈哈"); // String s1 = "李四哈哈";
System.out.println(s1);
//通过字节数组变成一个字符串
byte[] b = {97,98,99};
//参数1:字节数组 参数2:起始下标 参数3:长度
String s2 = new String(b, 0, b.length);
System.out.println(s2);
//通过字符数组变成一个字符串
char[] c = {'z','y','x'};
String s3 = new String(c, 0, c.length);
System.out.println(s3);
3.3 String类常用方法
//获取的方法----------------------------------------------------------------------------
String str = "abcn12c3fcds";
//charAt(index) 获取指定下标对应的字符,返回char类型
System.out.println(str.charAt(3));
//indexOf("字符串") 获取指定字符串在原字符串中的下标,如果不包含该字符串则返回-1
System.out.println(str.indexOf("cn2"));
//lastIndexOf("字符串") 与indexOf方法一致,区别:从后往前找
System.out.println(str.lastIndexOf("c"));
//length() 获取字符串的长度
System.out.println(str.length());
//判断的方法----------------------------------------------------------------------------
String str1 = "abcD";
//判断两个字符串是否相等
System.out.println("abcd".equals(str));
//判断两个字符串是否相等,忽略大小写
System.out.println("abcd".equalsIgnoreCase(str));
//判断字符串是否为空串 ""
System.out.println(str.isEmpty());
String str2 = "123478923";
//判断字符串是否以指定的字符串开头
System.out.println(str2.startsWith("12"));
//判断字符串是否以指定的字符串开头,指定开始位置
System.out.println(str2.startsWith("34", 2));
//判断字符串是否以指定的字符串结尾
System.out.println(str2.endsWith("23"));
//判断字符串中是否包含自定的字符串
System.out.println(str2.contains("SB"));
//其他方法----------------------------------------------------------------------------
// !!! 记得要重新赋值 !!!
String str = "hello,SB";
//将字符串与指定的字符串进行拼接
str = str.concat("world"); //str = str + "world";
System.out.println(str);
//字符串替换:将字符串中指定的字符串替换成指定的字符串
str = str.replace("SB", "**");
System.out.println(str);
//字符串截取,从指定的下标开始和结束 范围是左闭右开
str = str.substring(0, 5);
System.out.println(str);
//字符串截取,从指定的下标开始一直到最后
str = str.substring(6);
System.out.println(str);
//字符串切割,按照指定的字符串对原字符串进行切割
String str = "zhangsan lisi wangwu";
String[] s = str.split(" ");
System.out.println(Arrays.toString(s));
//去除字符串前后的空格
String str = " n你好。。 哈哈 ";
str = str.trim();
System.out.println(str);
String str = "abcd你好";
//将字符串变成字节数组
byte[] b = str.getBytes();
System.out.println(Arrays.toString(b));
//将字符串变成字符数组
char[] c = str.toCharArray();
System.out.println(Arrays.toString(c));
String str = "abcADC你好";
//将字符串中的字母变成大写
System.out.println(str.toUpperCase());
//将字符串中的字母变成小写
System.out.println(str.toLowerCase());
int i = 10;
//方式1:
String s = i+"";
//方式2:将其他的类型的数据转换成String类型
String s2 = String.valueOf(i);
System.out.println(s);
System.out.println(s2);
四、可变字符串
- StringBuffer
- StringBuilder
4.1 StringBuffer、StringBuilder类
常用方法
- append(String str);
- delete(int start, int end)
- insert(int offset, String str)
- reverse()
- toString()
public class StringBufferDemo {
public static void main(String[] args) {
//创建StringBuffer对象
StringBuffer sb = new StringBuffer();
//常用方法:
//在字符串的后面追加字符串
sb.append("abcdef");
System.out.println(sb); //abcdef
//删除字符串,从指定的下标开始和结束
sb.delete(2, 4);
System.out.println(sb);//abef
//在指定下标位置添加指定的字符串
sb.insert(2, "123");
System.out.println(sb);//ab123ef
//将字符串翻转
sb.reverse();
System.out.println(sb);//fe321ba
//将StringBuffer转换成String类型
String s = sb.toString();
System.out.println(s);
}
}
4.2 String、StringBuffer、StringBuilder区别
String、StringBuffer、StringBuilder区别
-
这三个类都可以用于表示字符串
-
1、String类是字符串常量类,一旦定义不能改变
-
2、StringBuffer、StringBuilder是可变的字符串,自带有缓冲区。默认缓冲区大小16个字符
-
3、StringBuffer是线程安全的,所以效率低 StringBuilder是线程不安全的,所以效率高
总结:在大量的字符串拼接的时候,使用 StringBuffer、StringBuilder。而不考虑线程安全的时候,选择StringBuilder,否则选择StringBuffer
public class Demo01 {
public static void main(String[] args) {
//需求:做100000次字符串拼接
//获取当前系统时间的毫秒数 4918
long start = System.currentTimeMillis();
String str = "";
for (int i = 0; i < 100000; i++) {
str = str + "a";
}
long end = System.currentTimeMillis();
System.out.println("耗时"+(end -start));
System.out.println("=================================");
//耗时:239
long start = System.currentTimeMillis();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 10000000; i++) {
sb.append("a");
}
long end = System.currentTimeMillis();
System.out.println("耗时"+(end -start));
System.out.println("=================================");
//耗时:90
long start = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000000; i++) {
sb.append("a");
}
long end = System.currentTimeMillis();
System.out.println("耗时"+(end -start));
}
}
五、String类面试题
public class StringDemo {
public static void main(String[] args) {
String s1 = "ab";
String s2 = "c";
String s3 = new String("abc");
String str1 = "abc";
String str2 = "abc";
String str3 = "ab" +"c";
String str4 = s1 +s2;
String str5 = new String("abc");
String str6 = new String("ab")+"c";
String str7 = s3.intern();
/**
* String str1 = "abc";
* String str2 = "abc";
* 这个“abc”存放在常量池中,
* 常量池的特点:
* 首先会去常量池中找是否有“abc”这个常量字符串,如果有直接用str1指向它,
* 如果没有将“abc”放到常量池中,用str1指向它
* 再使用去常量池中找有没有“abc”,这个时候已经有了,直接使用str2指向它。
*/
System.out.println(str1 == str2);//true
/**
* String str3 = "ab" +"c";
* 因为“ab”是常量与“c”拼接之后也会在常量池中。
*/
System.out.println(str1 == str3);//true
/**
* String s1 = "ab";
* String s2 = "c";
* 当s1和s2拼接的时候,jdk会将s1和s2转换成StringBuilder类型,然后进行拼接操作,
* 最终的内容实在堆内存中。
*/
System.out.println(str1 == str4);//false
/**
* String str1 = "abc"; 在常量池
* String str5 = new String("abc"); 在堆内存
*/
System.out.println(str1 == str5);//false
/**
* String str5 = new String("abc"); 在堆内存
* String str6 = new String("ab")+"c";在堆内存
*/
System.out.println(str5 == str6);//false
/**
* String str1 = "abc"; 在常量池
* String str6 = new String("ab")+"c"; 在堆内存
*/
System.out.println(str1 == str6);//false
/**
* String str7 = s3.intern();
* intern方法的含义:将String类型的对象指向常量池,如果有直接指向,如果没有放一个指向
*/
System.out.println(str1 == str7);//true
}
}
六、Date类
表示一个特定时间,精确到毫秒
public class DateDemo {
public static void main(String[] args) {
//创建Date类的对象 默认是系统当前时间
Date d1 = new Date();
//Fri Mar 12 11:35:00 CST 2021
System.out.println(d1);
/**
* year:年份,默认从1900开始计算
* month:月份,默认是0-11
* date:日期
*/
Date d2 = new Date(1998-1900, 2-1, 20);
System.out.println(d2);
Date d3 = new Date();
//返回当前date日期对应的时间的毫秒数 从1970年开始计算的毫秒数
System.out.println(d3.getTime()/1000/60/60/24/365);
Date d1 = new Date();
Date d2 = new Date(1998-1900, 2-1, 20);
//判断d1是否在d2之前
System.out.println(d1.before(d2));
//判断d1是否在d2之后
System.out.println(d1.after(d2));
//案例:计算自己活了多长时间
Date d1 = new Date(1998-1900, 2-1, 20);
Date d2 = new Date();
long time = d2.getTime() - d1.getTime();
System.out.println(time/1000/60/60/24);
}
}
七、SimpleDateFormat类
日期格式化类
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class SimpleDateFormatDemo {
public static void main(String[] args) {
//创建一个Date对象
Date date = new Date();
//创建日期格式化对象 2021年03月12日 14:15:30
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
//调用日期格式化对象的format方法
String time = sdf.format(date);
System.out.println(time);
//将字符串格式的时间转换成Date类型
String time = "2021-03-12 14:21:30";
//创建日期格式化对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//调用日期格式化对象的parse方法
try {
Date date = sdf.parse(time);
System.out.println(date);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
八、Calendar类
Calendar 类是一个抽象类,表示一个日历类。其包含有时间的三组方法
- get(字段) 获取指定字段的值
- set(字段,值) 设置指定字段的指定值
- add(字段,值) 在指定的字段添加或者减去指定的值
import java.util.Calendar;
public class CalendarDemo {
public static void main(String[] args) {
//创建日历类对象
//Calendar.getInstance();默认表示的系统当前时间
Calendar c = Calendar.getInstance();
//get方法
System.out.println(c.get(Calendar.YEAR));
//月份0-11
System.out.println(c.get(Calendar.MONTH)+1);
System.out.println(c.get(Calendar.DATE));
System.out.println(c.get(Calendar.HOUR_OF_DAY));
System.out.println(c.get(Calendar.MINUTE));
System.out.println(c.get(Calendar.SECOND));
//星期天是1
System.out.println(c.get(Calendar.DAY_OF_WEEK));
System.out.println("====================================================");
//set方法
c.set(Calendar.MONTH, 3-1);
System.out.println(c.get(Calendar.MONTH)+1);
c.set(Calendar.DAY_OF_WEEK, 7);
System.out.println(c.get(Calendar.DAY_OF_WEEK));
System.out.println("====================================================");
//add方法
c.add(Calendar.MONTH, -4);
System.out.println(c.get(Calendar.MONTH)+1);
System.out.println(c.get(Calendar.YEAR));
}
}
九、System类
系统类
常用方法:
- System.currentTimeMillis()
- 返回当前系统时间的毫秒数 从1970年开始计算
- System.exit(0)
- 终止Java虚拟机的运行 参数表示终止的状态 0表示正常退出
import java.text.SimpleDateFormat;
public class SystemDemo {
public static void main(String[] args) {
//System 系统类
//获取系统当前时间,返回自1970年开始以来时间的毫秒数
System.out.println(System.currentTimeMillis());
//格式化时间
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String time = sdf.format(System.currentTimeMillis());
System.out.println(time);
//结束当前虚拟机运行 0表示正常退出
System.exit(0);
System.out.println("执行吗?");
}
}
十、Math类
数学计算的工具类
public class MathDemo {
public static void main(String[] args) {
//求a的b次方法 参数1:底数 参数2:幂数
System.out.println(Math.pow(2, 10));
//求a平方根 参数1:要开方的数
System.out.println(Math.sqrt(100));
//求a立方根 参数1:要开立方的数
System.out.println(Math.cbrt(27));
//向上取整
System.out.println(Math.ceil(10.2));
//向下取整
System.out.println(Math.floor(10.9));
//四舍五入
System.out.println(Math.round(10.5));
//随机数 默认的范围[0,1)
System.out.println(Math.random());
//需求:随机一个两位数 [0,1)*90 [0,90) + 10
System.out.println((int)(Math.random()*90)+10);
}
十一、BigDecimal类
11.1为什么使用BigDecimal?
以下的代码的错误原因是0.9在计算中中的二进制是一个无限循环的
double保存时近似值,所以计算的结果不精确
double d1 = 1.0;
double d2 = 0.9;
System.out.println(d1-d2);//0.0999999998
11.2BigDecimal基本用法
- 位置:java.math包中。
- 作用:精确计算浮点数。
- 创建方式:BigDecimal bd=new BigDecimal(“1.0”)。
常用方法:
方法名 | 描述 |
---|---|
BigDecimal add(BigDecimal bd) | 加 |
BigDecimal subtract(BigDecimal bd) | 减 |
BigDecimal multiply(BigDecimal bd) | 乘 |
BigDecimal divide(BigDecimal bd) | 除 |
import java.math.BigDecimal;
import java.math.MathContext;
public class BigDecimalDemo {
public static void main(String[] args) {
double d1 = 1.0;
double d2 = 0.9;
//0.09999999999999998
System.out.println(d1-d2);
//使用BigDecimal类解决
//创建BigDecimal对象
BigDecimal bd1 = new BigDecimal("1.0");
BigDecimal bd2 = new BigDecimal("0.22");
System.out.println(bd1.add(bd2));
System.out.println(bd1.subtract(bd2));
System.out.println(bd1.multiply(bd2));
//ArithmeticException 算术异常
/**
* 参数说明:
* 参数1:被除数
* 参数2:保留小数位数
* 参数3:舍入模式
* ROUND_CEILING 向上取整
* ROUND_FLOOR 向下取整
* ROUND_HALF_UP 四舍五入
*/
System.out.println(bd1.divide(bd2,2,BigDecimal.ROUND_HALF_UP));
}
}