Java 常用类
内部类、Object类、包装类、String、BigDecimal类、时间类型
内部类
在一个类的内部再定义一个完整的类
成员内部类、静态内部类、局部内部类、匿名内部类
特点:
- 编译后可生成独立的字节码文件
- 内部类可直接访问外部类的私有成员,而不破化封装
- 可为外部类提供必要的内部功能组件
成员内部类
在类的内部定义,与实例属性、实例方法同一级别
创建内部类对象
Outer outer = new Outer();+Outer.Inner inner = out.new Inner();Outer.Inner inner = new Outer.new Inner();
特点:
- 成员内部类可以使用任何访问修饰符修饰
- 成员内部类可以直接访问外部类属性和方法
- 成员内部类属性和外部类属性同名时,使用
外部类类名.this.外部类属性 - 成员内部类不能包含静态成员,但可以包含静态常量
public class Outer {
private String name = "Tom";
public void show() {
System.out.println(Inner.KEY);
}
public class Inner {
public static final String KEY = "5563";
private String name = "John";
public void show() {
String name = "Rose";
// 就近原则,若没有局部变量则name为「John」
// 若没有内部成员变量,则name为「Tom」
System.out.println(name);
System.out.println(this.name);
System.out.println(Outer.this.name);
}
}
}
静态内部类
不依赖于外部类对象,可直接创建或类名访问,可声明静态成员
创建静态内部类对象
Outer.Inner inner = new Outer.Inner();- 静态内部类静态方法:
Outer.Inner.show(); - 可直接导包
cn.Outer.Inner;- 调用:
Inner.show()
- 调用:
特点
- 静态内部类可使用任何访问修饰符修饰
- 静态内部类不能直接访问外部类的实例属性和方法,可直接访问静态属性和方法
- 静态内部类可以包含静态成员
局部内部类
定义在外部类的方法中,作用是访问和创建对象,访问权限仅限于当前方法
特点
- 不能使用任何访问修饰符修饰
-
- 如果局部内部类所在的方法是非静态方法,可以直接访问外部类的实例属性和方法
- 如果局部内部类所在的方法是静态方法,只能访问外部类的静态属性和方法
- 局部内部类可以访问局部变量,局部变量必须使用
final修饰,「JDK8」以后final关键字可以省略(对象的声明周期长于局部变量)。 - 局部内部类不能声明静态成员,但可以声明静态常量。
public class localityInnerClass {
private String name = "name1";
public void show() {
final String city = "Peking";
// city = "122"; // 此处 city 不能再次赋值,city 应为「常量」用 final 修饰,可不写 final 但不能再次赋值
// 讨论到 栈、堆、方法区$常量池 的声明周期
class Inner3 {
public static final String work = "work";
private String like = "like1";
public void show2() {
System.out.println(like);
System.out.println(city);
System.out.println(name);
}
}
Inner3 inner3 = new Inner3();
inner3.show2();
}
}
匿名内部类
相当于没有名字的局部内部类,必须继承一个父类或实现一个接口
定义类、实现类、创建对象语法合并,并只能创建一个该类对象
优点
- 减少代码量
缺点
- 可读性差
特点
-
创建匿名内部类可以使用接口、抽象类、普通类必须实现接口或抽象类中抽象方法
-
匿名内部类不能手动创建构造方法,不能包含静态成员
-
匿名内部类中一般不包含特有方法,不能直接访问,可以通过方法调用或内部类调用
-
匿名内部类可以产生字节码文件,
类名$序号.class -
接口
public interface USB1 {
void service();
}
- 测试匿名内部类
public class TestAnonymity {
public static void main(String[] args) {
// 局部内部类
class USB2 implements USB1 {
@Override
public void service() {
System.out.println("鼠标链接...");
}
}
USB2 usb2 = new USB2();
usb2.service();
// 匿名内部类
USB1 usb1 = new USB1() {
@Override
public void service() {
System.out.println("键盘连接,...");
}
};
usb1.service();
// Lambda 表达式 接口中只有一个方法,代码块中只有一条语句
USB1 usb4 = () -> System.out.println("Mouse use");
usb4.service();
// 多条语句用大括号
USB1 usb3 = () -> {System.out.println("KeyBoard use");
System.out.println("start");};
usb3.service();
}
}
Object 类
超类、基类,所有类的直接或间接父类,位于继承树的最高层
- 任何类,如没有书写
extends显示继承某个类,都默认继承Object类,否则为间接继承 Object类中所定义的方法,是所有对象都具备的方法Object类型可以存储任何对象- 作为参数,可接受任何对象
- 作为返回值,可返回任何对象
Object 类中的方法
getClass()方法
- 返回引用中存储对象实际类型
- 返回
class 全限定名
- 返回
对象名.getClass().getName()- 返回
全限定名
- 返回
hashCode()方法
- 返回该对象的十进制的哈希码值
- debug时观察到的地址值为哈希码值的十六进制值
toString()方法
- 默认返回该对象的全限定名@十六进制哈希码值
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
- 将其进行重写,返回该对象属性的字符串表示
equals()方法
- 默认实现为:下面代码,比较两个对象地址值是否相同
public boolean equals(Object obj) {
return (this == obj);
}
- 覆盖
equals()方法步骤- 判断
obj是否为null - 比较两个引用是否指向同一个对象
- 判断两个引用指向的实际对象类型是否一致
- 强制类型转化
- 依次比较各个属性值是否相同
- 判断
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (this == obj) {
return true;
}
if (this.getClass() != obj.getClass()) {
return false;
}
if (obj instanceof Student) {
Student student = (Student) obj;
if (this.age == student.age && this.name.equals(student.name)) {
return true;
}
}
return false;
}
finalize()方法
- 当对象被判定为垃圾对象时,由JVM自动调用此方法,用以标记垃圾对象,进入回收队列
- 垃圾对象:没有有效引用指向此对象,为垃圾对象
- 垃圾回收:由GC销毁垃圾对象,释放数据存储空间
- 自动回收机制:JVM的内存耗尽,一次性回收所有垃圾对象
- 手动回收机制:使用
System.gc()通知JVM执行垃圾回收
包装类
基本数据类型所对应的引用数据类型,Object类可同一所有数据,包装类的默认是null。
| 基本数据类型 | 包装类型 |
|---|---|
| byte | Byte |
| short | Short |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
| char | Character |
| boolean | Boolean |
类型转换
- 基本数据类型和为包装类转换(以int和Integer为例)
装箱
Integer n1 = new Integer(20); // JDK9弃用
int n2 = 10;
Integer n3 = Integer.valueOf(n2); // 通过valueOf静态方法将基本数据类型转为包装类
拆箱
Integer n1 = new Integer(20);
int n2 = n1.intValue();
基本数据行与String类型转换
int n1 = Integer.parseInt("20");
// 这里要转换为int类型,字符串里面必须是一个整数。
// 要保证类型兼容
// 否则,抛出:NumberFormatException
- 包装类的一些其他方法及属性
Integer.MAX_VALUE // int最大值Integer.MIN_VALUE // int最小值Integer.toBinaryString(20) // 将数字转为二进制Integer.toHexString(20) // 将数字转为十六进制Integer.toOctalString(20) // 将数字转为八进制Integer.bitCount(20) // 一个数二进制数有多少个1
- 自动拆箱、装箱
JDK5.0之后,自动装箱、拆箱。基本数据类型和包装类自动转换
Integer n1 = 30; // 装箱,底层其实还是调用valueOf()
int n2 = n1; // 拆箱,底层调用intValue()
整数缓冲区
为什么要介绍这个呢?这里有个题可以看看
// 第一组
Integer i1=new Integer(100);//0x0000A001
Integer i2=new Integer(100);//0x0000B002
System.out.println(i1==i2);//==比较地址值 false
// 第二组
Integer i3=Integer.valueOf(100);//100
Integer i4=100;//100
System.out.println(i3==i4);//true 100==100
// 第二组
Integer i5=200;//new Integer(200);
Integer i6=200;//new Integer(200);
System.out.println(i5==i6);// false
第二组为什么是true,和valueOf()底层密不可分,底层中预先创建了256个常用的整数包装类型对象,在实际应用当中,对已创建的对象进行复用。这里就不详细介绍了。
String 类
Java 程序中的所有字符串文本都是此类的实例,字符串字面量是常量,具有不可变性,创建后不可改变。
常用创建方式
String str1 = new String("Java");
String str2 = "Java";
常用方法
-
public char charAt(int index):根据下标获取字符 -
public boolean contains(String str):判断当前字符串是否包含str -
public char[] toCharArray():将字符串转换成数组 -
public int indexOf(String str):查找str首次出现的下标,存在,则返回该下标;不存在返回-1 -
public int length():返回字符串长度 -
public String trim():去掉字符串前后的空格 -
public String toUpperCase():将小写转换成大写 -
public boolean endsWith(String str):判断字符串是否以str结尾 -
public String replace(char oldChar,char newChar):将旧字符串替换成新字符串 -
public String[] split(String str):根据str做拆分 -
public String subString(int beginIndex,int endIndex):在字符串中截取一个字符串
StringBuffer 和 StringBuilder
可在内存中创建可变的缓冲空间,存储频繁改变的字符串
位于java.lang包下
常用方法
append():追加insert():插入replace():替换delete():删除
区别
StringBuffer:可变长字符串,JDK1.0提供的,运行效率慢,线程安全。StringBuilder:可变长字符串,JDK5.0提供的,运行效率快,线程不安全。
BigDecimal 类
精准计算浮点数
位于java.math包下
创建方式
BigDecimal db = new BigDecimal("1.0");
常用方法
add(BigDecimal bd):加法运算substract(BigDecimal bd):减法运算multiply(BigDecimal bd):乘法运算divide(BigDecimal bd):除法运算
Math 类
Math类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。
位于java.lang包下
常用方法
static double random():生成[0,1)范围内的随机数static double pow(double a, double b):计算a的b次幂的值static double sqrt(double a):平方根static double cbrt(double a):
Random 类
此类的实例用于生成伪随机数流
- 位于
java.util包下 - 此类使用 48 位的种子,使用线性同余公式 (linear congruential form) 对其进行了修改所得。
- 若
long种子确定,则在不同程序中,相同次数产生的随机数是相同的。
Random random = new Random();
random.nextInt(20); // 获取[0,20)返回内的整数
Date 类
Date 表示精确的瞬间,精确到毫秒
Date中大部分方法都已经被calendar类中的方法取代
Date date = new Date(); // date 可以直接打印
// toLocaleString 更方便观察
date.getTime() // 获取当前时间毫秒值
Calendar 类
Calendar 提供了获取或设置各种日历字段的方法
位于java.util包下
Calendar的构造方法为protected修饰,无法直接创建该对象。因此要用Calendar的静态方法getInstance()来获取日历对象。
常用方法
| 方法名 | 说明 |
|---|---|
| void set(int year, int month, int date, int hourofday, int minute, int second) | 设置日历的时间 |
| int get(int field) | 返回给定日历字段的值 |
| void setTime(Date date) | 将Date转为Calendar |
| void getTime() | 将Calendar转为Date |
| void add(int field, int amount) | 给某个日历往前推时间,或往后推时间,amount参数是推几天 |
| long getTimeMillis() | 返回日历的时间毫秒值 |
SimpleDateFormat 类
SimpleDateFormat 是以与语言环境相关的方式来格式化和解析日期的类
位于java.text包下
格式化:日期 转为 文本 解析: 文本 转为 日期
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 创建对象
Date date = new Date(); // 创建日期对象
String string = simpleDateFormat.format(date); // 格式化
date = simpleDateFormat.parse(string); // 解析
System 类
System 系统类,主要用于获取系统的属性数据和其他操作
位于java.lang包下
常用方法
static void arraycopy():将一个数组拷贝到另一个数组,用于数组扩容static void currentTimeMillis():获取当前系统时间的毫秒值,用这个也可使测试一段程序的运行时间
// 在这里我们测试一下之前的 StringBuffer 和 StringBuilder 的运行速率怎么样
long start1 = System.currentTimeMillis();
StringBuffer stringBuffer = new StringBuffer();
int count1 = 0;
while (count1 < 100000000) {
stringBuffer.append("a");
count1++;
}
long end1 = System.currentTimeMillis();
System.out.println(end1 - start1); // 获得毫秒值
long start2 = System.currentTimeMillis();
StringBuilder stringBuilder = new StringBuilder();
int count2 = 0;
while (count2 < 100000000) {
stringBuilder.append("a");
count2++;
}
long end2 = System.currentTimeMillis();
System.out.println(end2 - start1);
static void gc():建议JVM启动垃圾回收器回收垃圾,只是建议static void exit(int status):退出JVM,如果是0则正常退出JVM,如果是非零则异常退出JVM
Runtime 类
每个 Java 程序都有一个 Runtime 实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime 方法获取当前运行时。
位于java.lang包下
常用方法
| 方法 | 说明 |
|---|---|
| Process exec() | 输入notepad可以启动记事本,输入程序入口的绝对路径也可启动程序 |
| void exit(int status) | 退出虚拟机 |
| void gc() | 和System系统类中的gc方法相同,只是System也是调用的这个gc()方法 |
| long totalMemory() | 获取内存总量,获取的应该是KB,除两次1024获得GB |
| long freeMemory() | 获取空闲内存量 |
| long maxMemory() | 虚拟机试图使用的最大内存量 |