Java常用类
一、内部类
1、内部类的概述
在一个类的内部定义一个完整的类。
例如:
class Body{//外部类
class Head{//内部类
}
}
2、内部类的特点
(1)编译之后可生成独立的字节码文件
(2)内部类可以直接访问外部类的私有成员,而不破坏封装
(3)可为外部类提供必要的内部功能组件
3、内部类的分类
3.1成员内部类
3.1.1成员内部类的概念
在类的内部定义,与实例变量,实例方法同级别的类。
3.1.2成员内部类的用法
-
外部类的一个实例部分,创建内部对象时,必须要依赖外部对象
例如
package com.wang.class_test; public class Outer { private String name = "张三"; private int age = 10; class Inner{ private String address = "太原"; private int num = 17636; public void print(){ System.out.println( name ); System.out.println( age ); System.out.println( address ); System.out.println( num ); } } public static void main(String[] args) { //创建内部类方法1 // Outer outer = new Outer(); // Inner inner = outer.new Inner(); //创建内部类方法2 Inner inner = new Outer().new Inner(); inner.print(); } }
结果
张三 10 太原 17636
-
当外部类和内部类存在重名属性,会优先访问内部类属性
例如
package com.wang.class_test; public class Outer { private String name = "张三"; private int age = 10; class Inner{ private String address = "太原"; private String name = "李斯"; private int num = 17636; public void print(){ System.out.println( name ); System.out.println( age ); System.out.println( address ); System.out.println( num ); } } public static void main(String[] args) { //创建内部类方法2 Inner inner = new Outer().new Inner(); inner.print(); } }
结果
李斯 10 太原 17636
如果将System.out.println( name );改为System.out.println(Outer.this.name );就可以获得外部类的name,在此处就不举例了。
-
成员内部类不能定义静态成员,但是可以定义静态常量
例如
class Body{//外部类
class Head{//内部类
private static String country = "中国"; //这句是错误的
private static final String country = "中国"; //这句是正确的
}
}
3.2静态内部类
3.2.1特点
不依赖外部类对象,可直接创建或通过类名访问,可声明静态成员
3.2.2静态内部类的用法
代码
package com.wang.class_test;
public class Outer {
private String name = "张三";
private int age = 10;
//静态内部类和外部类的用法一样,和外部类同级
static class Inner{
private String address = "太原";
private String name = "李斯";
//静态内部类可以定义静态成员
private static int num = 17636;
public void print(){
//1.要用外部类的属性或者方法,首先要创建外部类的对象
Outer outer = new Outer();
//2.调用外部类的属性
System.out.println( outer.name );
System.out.println( outer.age );
//调用静态内部类的属性
System.out.println( address );
System.out.println( name );
//调用静态成员,要用 类 来访问
System.out.println( Inner.num );
}
}
public static void main(String[] args) {
//创建内部类的对象
Outer.Inner inner= new Outer.Inner();
inner.print();
}
}
结果
张三
10
太原
李斯
17636
3.3局部内部类(用的不多)
3.3.1特点
定义在外部类方法中,作用范围和创建对象范围仅限于当前方法
3.3.2局部内部类的用法
代码
package com.wang.class_test;
//外部类
public class ClassTest {
private String name = "马德华";
private int age = 15;
public void show(){
//定义局部变量
String address = "太原";
//局部内部类
class Inner{
private int num = 151155;
public void show2(){
//打印外部类的属性
System.out.println(ClassTest.this.name);
System.out.println(ClassTest.this.age);
//访问内部类的属性
System.out.println(num);
//访问局部变量,jdk1.7要求,变量必须是常量,需要加final,jdk1.8会自动添加final
//相当于System.out.println(“太原”);
//因为局部变量会随着函数的结束消失,所以调用address时候应该是常量
//函数结束后,局部内部类和inner对象不会消失!!!
System.out.println(address);
}
}
//想要访问局部内部类,就要创建局部内部类的对象
Inner inner = new Inner();
inner.show2();
}
public static void main(String[] args) {
ClassTest classTest = new ClassTest();
classTest.show();
}
}
结果
马德华
15
151155
太原
3.4匿名内部类
3.4.1特点
- 没有类名的局部内部类(一切特征都与局部内部类相同)
- 必须继承一个父类或者实现一个接口
- 定义类、实现类、创建对象的语法合并,只能创建一个该类的对象
- 优点:减少代码量
- 缺点:可读性较差
3.4.2匿名内部类的用法
代码
package com.wang.class_test;
public interface Mouse {
void show();
}
package com.wang.class_test;
public class Use {
public static void main(String[] args) {
//使用匿名内部类优化(相当于创建了一个局部内部类)
Mouse mouse = new Mouse() {
@Override
public void show() {
System.out.println("开始好好学习!");
}
};
mouse.show();
}
}
结果
开始好好学习!
二、Object类
1、Object类的概述
(1)超类、基类、所有类的直接或间接父类,位于继承树的最顶层
(2)任何类,如果没有书写extends显示继承某个类,都默认直接继承Object类,否则为间接继承
(3)Object类中所定义的方法,是所有对象都具备的方法
(4)Object类型可以储存任何对象
作为参数,可以接受任何对象
作为返回值,可返回任何对象
2、Obejct的方法
2.1getClass()方法
getClass()返回值是当前对象的类类型,用来判断两个引用中实际存储对象类型是否一致。
代码
package com.wang.class_test;
public class Student {
private String name;
private int age;
public Student(String name, int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.wang.class_test;
public class getClass_test {
public static void main(String[] args) {
Student s1 = new Student("梁朝伟",18);
Class class1 = s1.getClass();
Student s2 = new Student("周星驰",18);
Class class2 = s2.getClass();
if(class1 == class2){
System.out.println("getClass1的类是:" + class1);
System.out.println("getClass2的类是:" + class2);
System.out.println("getClass1和getClass2属于同一个类");
}
}
}
结果
getClass1的类是:class com.wang.class_test.Student
getClass2的类是:class com.wang.class_test.Student
getClass1和getClass2属于同一个类
2.2hashCode()方法
该方法返回对象的哈希码值,哈希值是根据对象的地址或字符串或数字使用使用hash算法计算出来的int类型数值,一般情况下相同对象返回相同哈希码。
代码
package com.wang.class_test;
public class Student {
private String name;
private int age;
public Student(String name, int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.wang.class_test;
public class getClass_test {
public static void main(String[] args) {
Student s1 = new Student("梁朝伟",18);
Student s2 = new Student("周星驰",18);
//将s1的地址赋给s3
Student s3 = s1;
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
System.out.println(s3.hashCode());
}
}
结果
692404036
1554874502
692404036
对象s1和s3的哈希值相等!
2.3toString()方法
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
- 该方法返回该对象的字符串表示
代码
package com.wang.class_test;
public class Student {
private String name;
private int age;
public Student(String name, int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.wang.class_test;
public class getClass_test {
public static void main(String[] args) {
Student s1 = new Student("梁朝伟",18);
Student s2 = new Student("周星驰",18);
System.out.println(s1.toString());
System.out.println(s2.toString());
}
}
结果
com.wang.class_test.Student@29453f44
com.wang.class_test.Student@5cad8086
以上表示该对象是哪一个类,并且其哈希值是多少(十六进制表示)。
- 以上表示的结果对我们没有什么意义,所以当父类的方法无法满足自身要求时,我们可以重写方法。如下:
代码
package com.wang.class_test;
public class Student {
private String name;
private int age;
public Student(String name, int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package com.wang.class_test;
public class getClass_test {
public static void main(String[] args) {
Student s1 = new Student("梁朝伟",18);
Student s2 = new Student("周星驰",18);
System.out.println(s1.toString());
System.out.println(s2.toString());
}
}
结果
Student{name='梁朝伟', age=18}
Student{name='周星驰', age=18}
2.4equals()方法
public boolean equals(Object obj) {
return (this == obj);
}
- 默认实现为(this == obj),比较两个对象地址是否相同,其中this表示为调用equals方法的对象,obj表示为equals()括号里的对象。
代码
package com.wang.class_test;
public class Student {
private String name;
private int age;
public Student(String name, int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.wang.class_test;
public class getClass_test {
public static void main(String[] args) {
Student s1 = new Student("梁朝伟",18);
Student s2 = new Student("周星驰",18);
System.out.println(s1.equals(s2));
}
}
结果
false
- 此方法可以进行重写,比较两个对象的内容是否相同
代码
package com.wang.class_test;
import java.util.Objects;
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object obj) {
//判断两个对象是否为统一引用
if (this == obj) {
return true;
}
//判断obj是否为null
if(obj == null){
return false;
}
//左边是对象,右边是类,当对象是右边类或子类所创建对象时,返回true
if(obj instanceof Student){
System.out.println(obj.getClass());
//强制类型转换
Student s = (Student) obj;
//字符串的比较可以用equals
if (this.name.equals(s.getName()) && this.age == s.getAge() ){
return true;
}
}
return false;
}
}
package com.wang.class_test;
public class getClass_test {
public static void main(String[] args) {
Student s1 = new Student("梁朝伟",18);
Student s2 = new Student("梁朝伟",18);
System.out.println(s1.equals(s2));
}
}
class com.wang.class_test.Student
true
2.5finalize()方法
- 垃圾对象:没有有效引用指向此对象时,为垃圾对象。
- 当对象被判定为垃圾对象时,由JVM自动调用此方法,用以标记垃圾对象,进入回收队列。
- 垃圾回收:由GC销毁垃圾对象,释放数据存储空间。
- 自动回收机制:JVM的内存耗尽,一次性回收所有垃圾对象。
- 手动回收机制:使用System.gc();这个函数通过之JVM执行垃圾回收
接下来演示手动回收机制:
代码
package com.wang.class_test;
import java.util.Objects;
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public void finalize() throws Throwable{
System.out.println(this.name+"对象被回收了");
}
}
package com.wang.class_test;
public class getClass_test {
public static void main(String[] args) {
new Student("aaa",11);
new Student("bbb",11);
new Student("ccc",11);
new Student("ddd",11);
new Student("eee",11);
System.gc();
System.out.println("垃圾已回收");
}
}
结果
垃圾已回收
eee对象被回收了
ddd对象被回收了
ccc对象被回收了
bbb对象被回收了
aaa对象被回收了
三、包装类
1、特点
引用数据类型就是基本数据类型所对应的包装类,将基本数据类型变成对应的引用数据类型就会有属性和方法。
任何的对象都可以用Object的变量来接收!!!
2、类型转换
- 装箱:将基本类型转换成引用类型
- 拆箱:将引用类型转换成基本类型
package com.wang.class_test;
public class getClass_test {
public static void main(String[] args) {
//装箱:将基本类型转换成引用类型
int num1 = 18;
//使用Integer类创建对象
Integer integer1 = new Integer(num1);
Integer integer2 = Integer.valueOf(num1);
System.out.println("装箱");
System.out.println(integer1);
System.out.println(integer2);
//拆箱:将引用类型转换成基本类型
Integer integer3 = new Integer(100);
int num2 = integer3.intValue();
System.out.println("拆箱");
System.out.println(num2);
//JDK1.5之后,提供自动装箱、拆箱
int age = 15;
//自动装箱
Integer integer4 = age;
System.out.println("自动装箱");
System.out.println(integer4);
int num4 = integer4;
System.out.println("自动拆箱");
System.out.println(num4);
}
}
结果
装箱
18
18
拆箱
100
自动装箱
15
自动拆箱
15
2.1基本类型在栈
解释:int a = 4;这句话的意思是,在栈开辟了一块内存,名字叫a,里面的数值是4。
2.2引用类型在堆
解释:Integer b = new Integer(100);这句话的意思是,在堆里有一个对象,地址比如是001,里面是100,之后在栈里有一个变量b,会将堆里的地址001给了b,b指向堆里的对象。
3、字符串与基本类的转换
使用parsexxx();函数
package com.wang.class_test;
public class getClass_test {
public static void main(String[] args) {
//将基本类型转成字符串
int num = 255;
//使用“+”
String s1 = num + "";
//使用Integer的toString()
String s2 = Integer.toString(num,16);
System.out.println(s1);
System.out.println(s2);
//将字符串转成基本类型
String s3 = "155";
//使用Integer.parseInt()
int a = Integer.parseInt(s3);
System.out.println(a);
//Boolean字符串形式转成基本类型,“true”---》true,非“true”---》false
String s4 = "true";
String s5 = "ue";
boolean b1 = Boolean.parseBoolean(s4);
boolean b2 = Boolean.getBoolean(s5);
}
}
结果
255
ff
155
4、Integer缓冲区
package com.wang.class_test;
public class getClass_test {
public static void main(String[] args) {
//面试题
Integer integer1 = new Integer(100);
Integer integer2 = new Integer(100);
System.out.println(integer1 == integer2);
//Integer integer3 = 100;相当于以下
Integer integer3 = Integer.valueOf(100);//自动装箱
Integer integer4 = Integer.valueOf(100);
System.out.println(integer3 == integer4);
Integer integer5 = Integer.valueOf(200);//自动装箱
Integer integer6 = Integer.valueOf(200);
System.out.println(integer5 == integer6);
}
}
false
true
false
4.1Integer缓冲区面试题解释
第一组:integer1和integer2装着new出来的对象地址,两个对象地址肯定不一样,所以是错误的。
第二组:valueOf(int i)的源码是
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
static final int low = -128;
static final int high;
int h = 127;
high = h;
当i等于100的时候,没有超过low和high的范围,所以,会返回Integer缓冲区数组的地址,再将这个地址给了integer3和integer4,由于他俩都输入的是100,所以返回的地址也是一样的。所以是true。
第三组:当i等于200,超出了low和high的范围,所以会new Integer(i);,会new出两个不一样的对象,自然地址也就不一样了。
总结
Java预先创建了256个常用的整数包装类型对象,多次使用相同的底层对象可以有助于提高内存的优化,减少内存消耗
四、String类
1、概述
- 字符串是常量,创建之后不可以改变。
- 字符串字面值存储在字符串池中,可以共享。
- String name = “海绵宝宝”;产生一个对象,字符串池中存储。
- String str = new String(“章鱼哥”);产生两个对象,堆、池各一个对象
package com.wang.class_test;
public class getClass_test {
public static void main(String[] args) {
String name = "海绵宝宝";//"海绵宝宝"常量存在字符串池中
name = "派大星"; //"派大星"赋值给name变量,给字符串赋值时,
// 没有修改数据而是重新开辟内存
String name2 = "派大星";
//演示字符串的另一种创建形式,new String();
String str = new String("章鱼哥");
String str1 = new String("章鱼哥");
System.out.println(str == str1);//==比较的str存的地址
System.out.println(str.equals(str1));//equals比较的是地址对应的数据
}
}
false
true
1.1字符串内存图
2、方法
代码
package com.wang.class_test;
public class getClass_test {
public static void main(String[] args) {
//字符串方法的使用
//1、length();返回字符串的长度
//2、charAt(int index);返回某个位置的字符
//3、contains(String str);判断是否包含某个子字符串
//4、toCharArray();返回字符串对应的数组
//5、indexof();返回子字符串首次出现的位置
//6、lastIndexOf();返回字符串最后一次出现的位置
//7、trim();去掉字符串前后的空格
//8、toUpperCase();把小谢转成大写,toLowerCase();把大变小
//9、endWith(str);判断是否str结尾,startWith(str);判断是否已str开头;
//10、replace(char old,char new);用心的字符或者字符串代替旧的
//11、split();对字符串进行拆分
String name = "海绵宝宝";//空格也算一个字符
System.out.println(name.length());
System.out.println(name.charAt(2));//从位置0开始
System.out.println(name.contains("宝宝"));
String name1 = "海绵宝宝住在海底";//空格也算一个字符
System.out.println(Arrays.toString(name1.toCharArray()));
System.out.println(name1.lastIndexOf("宝"));
}
}
结果
4
宝
true
[海, 绵, 宝, 宝, 住, 在, 海, 底]
3
3可变字符串
StringBuffer:可变长字符串,JDK1.0以后提供,运行效率相对与StringBuilder慢,线程安全。
StringBuilder(单线程使用):可变长字符串,JDK5.0以后提供,运行效率相对与StringBuffer快,线程不安全。
3.1测试速度
package com.wang.class_test;
public class Demo1 {
public static void main(String[] args) {
//开始时间
long start = System.currentTimeMillis();
//String string = "";用时间405
StringBuilder sb = new StringBuilder();
for (int i = 0;i < 9999;i ++){
sb.append(i);
}
System.out.println(sb.toString());
long end = System.currentTimeMillis();
System.out.println("StringBuilder用时:"+(end-start));
}
}
结果
StringBuilder用时:4
3.2用法
代码
package com.wang.class_test;
import java.sql.Array;
import java.util.Arrays;
public class getClass_test {
public static void main(String[] args) {
//StringBuffer sb = new StringBuffer();
StringBuilder sb = new StringBuilder();
//1、append();追加
sb.append("海绵宝宝");
System.out.println(sb.toString());
sb.append("派大星");
System.out.println(sb.toString());
//2、inset();添加
sb.insert(0,"搞笑的");
System.out.println(sb.toString());
//3、replace();替换
sb.replace(0,3,"hello");//含头不含尾
System.out.println(sb.toString());
//4、delete();删除
sb.delete(0,sb.length());
System.out.println(sb.length());
}
}
结果
海绵宝宝
海绵宝宝派大星
搞笑的海绵宝宝派大星
hello海绵宝宝派大星
0
五、BigDecimal类
1、原因
很多实际应用中要求精确运算,而double是近似值存储,不符合要求,需要BigDecimal。
2、相关信息
位置:java.math包
作用:精确计算浮点数
创建方式:BigDecimal bd = new BigDecimal(“1.0”);
3、用法
package com.wang.class_test;
import java.math.BigDecimal;
public class Demo1 {
public static void main(String[] args) {
//平时算法
double result = (1.4 - 0.5)/0.9;
System.out.println("double:" + result);
//BigDecimal,大的浮点数精确计算
BigDecimal bd1 = new BigDecimal("1.0");
BigDecimal bd2 = new BigDecimal("0.9");
//减法
BigDecimal r1 = bd1.subtract(bd2);
System.out.println("BigDecimal减法:" + r1);
//加法
BigDecimal r2 = bd1.add(bd2);
System.out.println("BigDecimal加法:" + r2);
//乘法
BigDecimal r3 = bd1.multiply(bd2);
System.out.println("BigDecimal乘法:" + r3);
//除法
BigDecimal r4 = new BigDecimal("1.4")
.subtract(new BigDecimal("0.5"))
.divide(new BigDecimal("0.9"));
System.out.println("BigDecimal除法:" + r4);
//除法除不尽
BigDecimal r5 = new BigDecimal("10").divide(new BigDecimal("3"),2,BigDecimal.ROUND_HALF_UP);
System.out.println("BigDecimal除不尽:" + r5);
}
}
结果
double:0.9999999999999999
BigDecimal减法:0.1
BigDecimal加法:1.9
BigDecimal乘法:0.90
BigDecimal除法:1
BigDecimal除不尽:3.33
六、System类
1、用法
System系统类,主要用于获取系统的属性数据和其他操作,构造方法私有!!
2、方法
package com.wang.class_test;
import java.util.Objects;
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public void finalize() throws Throwable{
System.out.println(this.name+"对象被回收了");
}
}
package com.wang.class_test;
import java.math.BigDecimal;
public class Demo1 {
public static void main(String[] args) {
//arraycopy:数组的复制
//src:源数组
//srcPos:从那个位置开始复制
//dest:目标数组
//destPos:目标数组的位置
//length:复制的长度
//System.arraycopy(src,srcPos,dest,destPos,length);
System.out.println("*****************arraycopy()*********************");
int[] arr = {20,18,55,65,14,2,3,5};
int[] dest = new int[8];
System.arraycopy(arr,4,dest,0,4);
for (int i = 0;i < dest.length;i++){
System.out.println(dest[i]);
}
System.out.println("*****************currentTimeMillis()*********************");
//currentTimeMillis()
System.out.println(System.currentTimeMillis());
System.out.println("*****************gc()*********************");
//System.gc();告诉垃圾回收器回收
new Student("海绵宝宝",5);
new Student("派大星",5);
new Student("章鱼哥",1);
System.gc();
System.out.println("*****************exit()*********************");
//System.exit();推出JVM
System.exit(0);
System.out.println("程序结束");//程序不会走这一句话,因为已经推出了
}
}
*****************arraycopy()*********************
14
2
3
5
0
0
0
0
*****************currentTimeMillis()*********************
1636952903824
*****************gc()*********************
派大星对象被回收了
章鱼哥对象被回收了
海绵宝宝对象被回收了