- 匿名内部类是一个没有类名的局部内部类!(一切特征都是与局部内部类相同!)
- 必须继承一个父类或者实现一个接口!
- 定义类、实现类、创建对象的语法合并,只能创建一个该类的对象
- 优点:减少代码量
- 缺点:可读性较差
先编写一个USB接口,让其他类去实现这个接口
package com.ClassTest.Anonymous;
//接口
public interface USB {
//服务方法
void service();
}
在编写实现接口类
package com.ClassTest.Anonymous;
//测试
public class TestUSB {
//重写服务
public static void main(String[] args) {
//使用匿名内部类优化(相当于创建了一个局部内部类)
USB usb = new USB() {
@Override
public void service() {
System.out.println("链接电脑成功,风扇开始启动了。。。。。");
}
};
usb.service();
}
}
综上,可以看出,正常的一个接口是不能被实例化的,而以上代码直接将接口进行实例化,说白了就是默认创建了一个匿名内部类,是我们看不到的类,这个是跟局部内部类一样的,都是在方法中所创建,而这个匿名类内部类就是在main方法的下面!可以打开class文件目录查看一下是否生成新的文件!
可以看出,系统是默认生成了一个TestUSB$1的class文件,这个就是匿名内部类文件!
二、Object类方法摘要概述:Object类是一个超类、基类,所有类的直接或间接父类,位于继承树的最顶层!
任何类,如没有书写extends显示继承某个类,都默认直接继承Object类,否则为间接间接继承!
Object类中所定义的方法,是所有对象都具备的方法!
Object类型可以存储任何对象:作为参数,可以接受任何对象。作为返回值,可以返回任何对象!
- clone():创建并返回此对象的一个副本。
- equals(object obj):指示其他某个对象是否与此对象“相等”。
- finalize():当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
- getClass():返回此object的运行时类。
- hashCode():返回该对象的哈希码值!
- notify():唤醒在此对象监视器上等待的单个线程
- notifyAll():唤醒在此对象监视器上等待的所有线程
- toString():返回该对象的字符串表示。
- wait():在其他线程调用此对象的notify()方法或notifyAll()方法前,导致当前线程等待。
- wait(long timeout):在其他线程调用此对象的notify()方法或notifyAll()方法,或超过指定的时间量前,导致当前线程等待。
- wait(long timeout,int namos):在其他线程调用此对象的notify()方法或notifyAll()方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量前,导致当前线程等待。
- public final Class> getClass(){}
- 返回引用中存储的事迹对象类型
- 应用:通常用于判断两个引用中实际存储对象类型是否一致
下面使用代码测试一下,首先创建一个普通类,用来封装属性
package com.ClassTest.Object.getClass;
//创建学生类,用来测试getClass运行时类是否相同
public class Student {
private String name;
private int age;
//无参构造器
public Student(){
}
//有参构造器 参数列表是名字跟年龄
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.ClassTest.Object.getClass;
public class TestStudent {
public static void main(String[] args) {
Student s1 = new Student("菲",18);
Student s2 = new Student("堂",18);
Class class1 = s1.getClass();
Class class2 = s2.getClass();
if (class1.equals(class2)){
System.out.println("s1跟s2属于同一个类型!");
}else{
System.out.println("s1跟s2不属于同一个类型!");
}
}
}
二、hashcode方法综上,可以看出s1跟s2的类是同一个类!
- public int hashCode(){}
- 返回该对象的哈希码值
- 哈希值根据对象的地址或字符串或数字使用hash算法计算出来的int类型的数值
- 一般情况下相同对象返回相同哈希码值!
继续使用上面getClass方法中的测试类!
package com.ClassTest.Object.getClass;
public class TestStudent {
public static void main(String[] args) {
Student s1 = new Student("菲",18);
Student s2 = new Student("堂",18);
Class class1 = s1.getClass();
Class class2 = s2.getClass();
if (class1.equals(class2)){
System.out.println("s1跟s2属于同一个类型!");
}else{
System.out.println("s1跟s2不属于同一个类型!");
}
Student s3 = s1;
System.out.println(s1.hashCode()); //哈希值是1163157884
System.out.println(s2.hashCode()); //哈希值是1956725890
System.out.println(s3.hashCode()); //哈希值是1163157884
}
}
三、toString方法综上,能看到如果输出s1对象中的哈希值,那就是1163157884,s2对象中的哈希值是1956725890,而s3等于s1的哈希值,所以跟s1的哈希值相同!
- public String toString(){}
- 返回该对象的字符串表示(表现形式)
- 可以根据程序需求覆盖该方法,如:展示对象各个属性值!
继续使用测试类,来查看toString方法返回的值
package com.ClassTest.Object.getClass;
public class TestStudent {
public static void main(String[] args) {
//1、getClass方法
System.out.println("---------------1、getClass方法-------------------");
Student s1 = new Student("菲",18);
Student s2 = new Student("堂",18);
Class class1 = s1.getClass();
Class class2 = s2.getClass();
if (class1.equals(class2)){
System.out.println("s1跟s2属于同一个类型!");
}else{
System.out.println("s1跟s2不属于同一个类型!");
}
//2、hashCode方法
System.out.println("---------------2、hashCode方法-------------------");
Student s3 = s1;
System.out.println(s1.hashCode()); //哈希值是1163157884
System.out.println(s2.hashCode()); //哈希值是1956725890
System.out.println(s3.hashCode()); //哈希值是1163157884
//3、toString方法
System.out.println("---------------3、toString方法-------------------");
System.out.println(s1.toString());
System.out.println(s2.toString());
System.out.println(s3.toString());
}
}
综上,我们得出的结果是类的全名称以及@符号的哈希值。这个@符号后的值跟上面hashCode方法得出的哈希值是一样的!显然这个结果不是我们自己想要的结果,不应是输出类的路径,应该是方法中的值,所以我们可以再重写一次这个toString的方法,也就是将返回值重写成name+age!
public String toString(){ //在学生类中重写父类的toString方法
return name+":"+age;
}
查看测试类的结果
综上,只要重写就能得出具体的值了!
四、equals()方法
- public boolean equals(object obj){}
- 默认实现为(this == obj),比较两个对象地址是否相同。
- 可进行覆盖,比较两个对象的内容是否相同!
同样适用前面的测试方法,来测试是否相同
//4、equals方法
System.out.println("---------------4、equals方法-------------------");
System.out.println(s1.equals(s2));
Student s4 = new Student("小明",17);
Student s5 = new Student("小明",17);
System.out.println(s4.equals(s5));
综上,可以看出,这个结果都是返回的false,因为当前object类的equals方法,对比的是两个对象的地址!而不是值,如果想要值相同,那么就需要重写equals方法!
- equals方法覆盖步骤:
- 比较两个引用是否指向同一个对象
- 判断obj是否为null
- 判断两个引用指向的实际对象类型是否一致
- 强制类型转换
- 依次比较各个属性值是否相同
在以下Student类中去进行重写equals方法!
public boolean equals(Object obj) {
//1、判断两个引用是否指向同一个对象
if (this == obj){
return true;
}
//2、判断obj是否为null
if (obj == null){
return false;
}
//3、instanceof判断两个引用指向的实际对象类型是否相同
if (obj instanceof Student) {
//类型转换
Student s = (Student) obj;
//4、依次比较各个属性值是否相同
if (this.name.equals(s.getName())&&this.age == s.getAge()){
return true;
}
}
return false;
}
五、finalize()方法综上结果,可以看出,重写方法之后返回的内容跟我预想的就一样了!
- 当对象被判定为垃圾对象时,由JVM自动调用此方法,用以标记垃圾对象,进入回收队列
- 垃圾对象:没有有效引用指向此对象时,为垃圾对象
- 垃圾回收:由GC销毁垃圾对象,释放数据存储空间。
- 自动回收机制:JVM的内存耗尽,一次性回收所有垃圾对象。
- 手动回收机制:使用System.gc(); 通知JVM执行垃圾回收!
首先将finalize方法进行重写,因为需要准确的看到输出内容!一样是在Student类中重写!
//重写funalize方法
protected void finalize()throws Throwable{
System.out.println(this.name+"对象被回收了!");
}
然后新建一个Student2的类,用来测试输出!
package com.ClassTest.Object.getClass;
public class Student2 {
public static void main(String[] args) {
//实例化一个对象
Student s1 = new Student("aaa",20);
Student s2 = new Student("bbb",20);
Student s3 = new Student("ccc",20);
//new一个对象,但是没有引用值,也就是没有被调用
new Student("aaa",20);
new Student("bbb",20);
new Student("ccc",20);
new Student("ddd",20);
//5、finalize回收垃圾
System.out.println("---------------5、finalize回收垃圾-------------------");
System.gc();
System.out.println("回收垃圾");
}
}
综上,可以看出来,当实例化一个对象时,而这个对象并没有引用值去调用它,当你需要回收的时候,JVM就会判断它们是一个垃圾,然后进行回收,也就达到了清理内存的好处!
三 、包装类
什么是包装类 ?
- 基本类型所对应的引用数据类型!
- Object可统一所有数据,包装类的默认值是null
| 基本数据类型 | 包装类型 |
|---|---|
| btye | Byte |
| short | Short |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
| boolean | Boolean |
| char | Character |
- 引用类型存放在堆里面
- 数据基本类型存放在栈里面
- 装箱:把栈里面的数据加载到堆里面叫装箱,也就是把基本类型转换成引用类型叫装箱
- 拆箱:把堆里面的对象拿到栈里面叫拆箱,把引用类型转换成基本类型叫拆箱!
创建一个Demo01的类,用来演示装箱与拆箱的操作
package com.ClassTest.Packaging;
public class Demo01 {
public static void main(String[] args) {
//自动装箱:基本类型转换成引用类型,也就是装箱
int age = 30;
Integer integer1 = age;
System.out.println("自动装箱");
System.out.println(integer1);
System.out.println("*----------------------------------*");
//自动拆箱:引用类型转换成基本类型,也就是拆箱
int age2 = integer1;
System.out.println("自动拆箱");
System.out.println(age2);
}
}
结果图
综上,可以看出是jdk1.5以上,便可以完成自动装箱跟拆箱的操作了!也就是基本类型与引用类型之间的互相转换
注:文章仅做个人学习日记,不做学习建议,学习来源:千峰教育



