常用类之内部类与Object类
常用类
1.内部类
-
什么是内部类
- 内部类:就是在java类中,再写一个或多个类。在一个类的内部再定义一个完整的类,编译之后生成独立class文件,内部类可以直接访问外部类的私有成员,而不破坏封装性;可为外部类提供必要的内部功能;
-
内部类的分类
- 1.成员内部类:在一个类中定义一完整的类
- 2.静态内部类:加static
- 3.局部内部类:在方法中定义一个类
- 4.匿名内部类:在接口和抽象类中用的比较多
-
内部类特点:
- 编译之后可生成独立的字节码文件 Outer$Inner.class Outer.class
- 内部类可直接访问外部类私有成员,而不破坏封装
- 可为外部类提供必要的内部功能组件
-
内部类语法:
class Outer {
class Inner {
// 也会生成class文件
}
}
1.1.成员内部类
- 成员内部类特点
- 在类的内部定义,与实例变量、实例方法同级别的类
- 外部类的一个实例部分,创建内部类对象时,必须依赖外部类对象
// 创建外部类对象 Outer outer = new Outer(); // 创建内部类对象 Outer.Inner inner = outer.new Inner();
- 当外部类、内部类存在重名属性时,会优先访问内部类属性,若需要访问外部类属性,使用 Outer.this.属性
- 成员内部类不能包含静态成员,但可以包含静态常量(final)(内存分配会冲突)。如:private static final String name;
1.1 内部类代码演示
package classes.demo01;
//成员内部类
//外部类
public class Outer {
//实例变量
private String name="小明";
private int age =18;
private static int ages=20;
public void show(){
System.out.println("外部类的方法");
}
//内部类
class Inner{
private String name="李四";
private String email="188888888";
//成员内部类不能定义静态成员static,但可以包含静态常量 final
private static final String country="中国";
public void innershow(){
System.out.println("内部类的方法");
//打印外部类的属性,属性和外部类的属性名字相同,需要使用 Outer.this 才能打印出小明
System.out.println(name);// 默认打印李四
System.out.println(Outer.this.name);
System.out.println(Outer.this.age);
System.out.println(Inner.country); //类名.属性 打印静态的属性
//打印内部类的属性
System.out.println(this.name);
System.out.println(this.email);
}
}
}
package classes.demo01;
public class Test {
public static void main(String[] args) {
/*
//1 创建外部类对象
Outer outer = new Outer();
//2 创建内部类对象
Outer.Inner inner = outer.new Inner();
inner.innershow();
*/
//一步的写法
Outer.Inner inner = new Outer().new Inner();
inner.innershow();
}
}
运行结果
内部类的方法
李四
小明
18
中国
李四
188888888
1.2静态内部类
- 静态内部类特点
-
不依赖外部类,可直接创建或通过类名访问,可声明静态成员
-
相当于一个外部类,级别和外部类相同外部类可以包含什么,这个内部类就可以包含什么
-
只能直接访问外部类的静态成员(实例成员需实例化外部类对象)
Outer.Inner inner = new Outer.Inner(); Outer.Inner.show();
-
可以在内部类前加 static 修饰,加了static修饰符之后,静态内部类级别与外部类相同。(只有内部类才可以static修饰,普通的类不可以)
-
1.2 静态内部类代码演示
package classes.demo02;
//静态内部类
public class Outer {
private String name="张三";
private int age=20;
public void show(){
System.out.println("外部类的方法");
}
//静态内部类:和外部类相同,一个级别
static class Inner{
private String address="北京";
private String phone="12345678";
//静态成员
private static int count=1000;
public void innerShow(){
System.out.println("静态内部类的方法");
//调用静态内部类的属性
System.out.println(address);
System.out.println(phone);
//调用静态内部类的静态属性
System.out.println(Inner.count);
//调用外部类的属性时
//1 先创建外部类对象
Outer outer = new Outer();
outer.show();
//2 调用外部类对象属性
System.out.println(outer.age);
System.out.println(outer.name);
}
}
}
package classes.demo02;
public class Test {
public static void main(String[] args) {
//调用静态内部类方法 // 直接创建静态内部类对象
Outer.Inner inner = new Outer.Inner();
//调用方法
inner.innerShow();
}
}
运行结果
静态内部类的方法
北京
12345678
1000
外部类的方法
20
张三
1.3局部内部类
- 局部内部类特点
-
定义在外部类方法中,作用范围和创建对象范围仅限于当前方法
-
局部内部类不能加任何访问修饰符;
-
局部内部类访问外部类当前方法中的局部变量时,因无法保障变量的生命周期与自身相同,变量必须修饰为final
-
限制类的使用范围。
-
1.3 局部内部类代码演示
package classes.demo03;
//局部内部类
public class Outer {
private String name="小子";
private int age=12;
public void show(){
//定义局部变量 // jdk1.8及以后自动添加final
final int phone=66;
final String address="上海";
//局部内部类:注意不能加任何访问修饰符
class Inner{
//局部内部类的属性
private String email="1234556677";
private String phone = "123456";
public void innerShow(){
System.out.println("局部内部类方法");
//局部内部类的属性
System.out.println(email);
System.out.println(phone);
//访问外部类属性
System.out.println(name);//省略了outer.this
System.out.println(Outer.this.name);
System.out.println(Outer.this.age);
//访问局部变量,jdk1.7要求,局部变量必须时常量,
// jdk1.8及以后自动添加final
System.out.println(address);
System.out.println("上海");
}
}
//创建局部类对象
Inner inner = new Inner();
inner.innerShow();
}
}
package classes.demo03;
public class Test {
public static void main(String[] args) {
// 创建外部类对象调用
Outer outer = new Outer();
outer.show();
}
}
运行结果
局部内部类方法
1234556677
123456
小子
小子
12
上海
上海
1.4匿名内部类
- 匿名内部类特点
-
没有类名的局部内部类(一切特征都与局部内部类相同)
-
必须继承一个父类或者实现一个接口
-
定义类、实现类、创建对象的语法合并,只能创建一个该类的对象(以实现接口为例,先创建一个名为 Inter 的接口,内部方法为 method。通常创建一个局部内部类是有类名称的,而上述匿名内部类相当于创建了一个没有名字的局部内部类来实现了 Inter 接口,是一个语法合并的形式)
-
优点:减少代码量 缺点:可读性较差
-
1.4 匿名内部类代码演示
package classes.demo04;
//接口
public interface Usb {
//服务方法
void service();
}
package classes.demo04;
public class Mouse implements Usb {
@Override
public void service() {
System.out.println("连接USB成功,鼠标开始工作");
}
}
package classes.demo04;
import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
import org.w3c.dom.ls.LSOutput;
public class Test {
public static void main(String[] args) {
class fan implements Usb{
@Override
public void service() {
System.out.println("连接USB成功,风扇开始工作");
}
}
//使用局部内部类创建对象
Usb usb1 = new fan();
usb1.service();
// 使用匿名内部类优化(相当于创建了一个局部内部类)
Usb usb = new Usb(){//new 后面可以是接口也可以是抽象类或者父类 大括号里重写方法
@Override
public void service() {
System.out.println("连接风扇成功,开始工作了");
}
}; // 注意后面的 ;
usb.service();
}
}
运行结果
连接USB成功,风扇开始工作
连接风扇成功,开始工作了
2.Object类
-
超类、基类,所有类的直接或间接父类,位于继承树的最顶层
-
任何类,如没有书写extends显示继承某个类,都默认直接继承Object类,否则为间接继承
-
Object类中所定义的方法,是所有对象都具备的方法
-
Object类型可以存储任何对象
-
作为参数:可接受任何对象
-
作为返回值:可返回任何对象
-
2.1 object 类常用方法
1.getClass()方法
public final Class<?> getClass() {}
- 返回引用中存储的实际对象类型
- 应用:通常用于判断两个引用中实际存储对象类型是否一致
2.hashCode方法
public int hashCode (){}
- 返回该对象的哈希码值
- 哈希值根据对象的地址或字符串或数字使用hash算法计算出来的int类型的数值。
- 一般情况下相同对象返回相同哈希码
3.toString方法
public String toString(){}
- 返回该对象的字符串表示(表现形式)
- 可以根据程序需求覆盖该方法(重写:快捷键Alt+insert),如:展示对象各个属性值。
4.equals方法
public boolean equals(Object obj){}
- 默认实现为(this == obj),比较两个对象地址是否相同
-
可进行覆盖(重写),比较两个对象的内容是否相同
-
equals()方法覆盖步骤:
-
1.比较两个引用是否指向同一个对象
-
2.判断obj是否为null
-
3.判断两个引用指向的实际对象类型是否一致
-
4.强制类型转换
-
5.依次比较各个属性值是否相同
-
5.finalize方法
- 当对象被判定为垃圾对象时,由JVM自动调用此方法,用以标记垃圾对象,进入回收队列
-
垃圾对象:没有有效引用指向此对象时,为垃圾对
-
垃圾回收:由gc销毁垃圾对象,释放数据存储空间
-
自动回收机制:JVM的内存耗尽,一次性回收所有垃圾对象
-
手动回收机制:使用System.gc();通知JVM执行垃圾回收
2.2 Object类常用方法代码演示:
package classes.demo06;
import java.util.Objects;
public class Student {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student() {
}
public Student(int age, String name) {
this.age = age;
this.name = name;
}
//快捷建:Alt+enter 选toString 方法
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
@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(age, name);
}
//打印finalize 会有提示重写
@Override
protected void finalize() throws Throwable {
System.out.println(this.name+"垃圾被清理了");
}
}
package classes.demo06;
public class TestStudent {
public static void main(String[] args) {
// 1. getClass()方法 :
System.out.println("----------------1. getClass()-----------------");
Student student1 = new Student(20,"aaa");
Student student2 = new Student(20,"ccc");
//判断S1和S2是不是同一个类型
if (student1.getClass()==student1.getClass()){
System.out.println("是同一类型");
}else{
System.out.println("不是同一类型");
}
//2.hashcode() 方法
System.out.println("----------------2.hashcode() -----------------");
Student student3 = new Student();
Student student4 = new Student();
System.out.println(student3.hashCode());
System.out.println(student4.hashCode());
Student student5=student3;
System.out.println(student5.hashCode());
//3. toString 方法
System.out.println("----------------3. toString -----------------");
System.out.println(student1.toString());
System.out.println(student2.toString());
//4.equals() 方法 判断两个对象是否相等
System.out.println("----------------4. equals() -----------------");
Student student6 = new Student(17, "小子");
Student student7 = new Student(17, "小子");
System.out.println( student6.equals(student7));
}
}
运行结果
----------------1. getClass()-----------------
是同一类型
----------------2.hashcode() -----------------
961
961
961
----------------3. toString -----------------
Student{age=20, name='aaa'}
Student{age=20, name='ccc'}
----------------4. equals() -----------------
true
package classes.demo06;
public class TestStudent2 {
public static void main(String[] args) {
//System.gc(); 垃圾回收
Student student1 = new Student(17,"aaaa");
Student student2 = new Student(17,"bbbb");
Student student3 = new Student(17,"cccc");
new Student(17,"ddddd");
new Student(17,"eeeee");
new Student(17,"fffff");
// 回收垃圾 使用System.gc();通知JVM执行垃圾回收
System.gc();
System.out.println("垃圾已经回收");
}
}
运行结果
垃圾已经回收
eeeee垃圾被清理了
fffff垃圾被清理了
ddddd垃圾被清理了
————————————————————————————————————————————————————————————————————————————