09.内部类
什么是内部类?
-
概念:在一个类的内部再定义一个完整的类。
-
特点:
-
编译之后可以生成独立的字节码文件。
-
内部类可以直接访问外部类的私有成员,而不破坏封装。
-
可为外部类提供必要的内部功能组件。
-
package Inner; // 身 体 public class Test01 { private String name ;//私有成员变量 public static void main(String[] args) { } // 头 部 class Header{ // 内部类 public void show(){ System.out.println(name); } } }
-
-
成员内部类
-
在类的内部定义,与实例变量、实例方法同级别的类。
-
外部类的一个实例部分,创建内部类对象时,必须依赖外部类对象
-
Outer out = new Outer();
-
Inner in = out.new Inner();
-
package Inner; import Inner.Outer.Inner; public class TestOuter { public static void main(String[] args) { // // 1.创建外部类对象 // Outer outer = new Outer(); // // 2.创建内部类对象 // Inner inner = outer.new Inner(); // 一步到位 Inner inner = new Outer().new Inner(); inner.show(); } }package Inner; public class Outer { // 实例变量 private String name = "张三"; private int age = 20; // 内部类 class Inner{ private String address = "北京"; private String phone = "110"; // 方法 public void show(){ // 打印外部类的属性 System.out.println(name); System.out.println(age); // 打印内部类的属性 System.out.println(address); System.out.println(phone); } } }
-
-
当外部类、内部类存在重名属性是,会优先访问内部类属性。
-
package Inner; public class Outer { // 实例变量 private String name = "张三"; private int age = 20; // 内部类 class Inner{ // 属性和外部类属性相同,优先访问内部类属性 private String name = "李四"; private String address = "北京"; private String phone = "110"; // 方法 public void show(){ // 打印外部类的属性 System.out.println(name);//输出:李四 // 打印外部类属性:Outer.this.。。。 System.out.println(Outer.this.name);//输出:张三 System.out.println(age); // 打印内部类的属性 System.out.println(address); System.out.println(phone); } } }
-
-
成员内部类不能调用静态成员
-
package Inner; public class Outer { // // 内部类 class Inner{ // private static String name = "中国";//内部类不能包含静态成员 private final static String country = "中国"; // 特殊情况 } }
-
静态内部类
-
不依赖外部类对象,可以直接创建或通过类名访问,可声明静态成员。
-
只能直接访问外部类的静态成员(实例成员需实例化外部类对象)
-
Outer.Inner = new Outer.Inner(); Outer.Inner.show(); -
package staticInner; public class TestOuter { public static void main(String[] args) { // 直接创建内部类对象 Outer.Inner inner = new Outer.Inner(); //调用方法 inner.show(); } }package staticInner; // 外部类 public class Outer { private String name = "xxx"; private int age = 18; // 静态内部类,和外部类相同 static class Inner{ private String address = "上海"; private String phone = "111"; // 静态成员 private static int count = 1000 ; public void show(){ //调用外部类的属性: // 1.先创建外部类对象 Outer outer = new Outer(); // 2.调用外部类对象的属性 System.out.println(outer.age); System.out.println(outer.name); // 调用静态内部类属性 System.out.println(address); System.out.println(phone); // 调用静态内部类的静态属性 System.out.println(Inner.count); } } }
-
局部内部类
-
定义在外部类方法中,作用范围和创建对象范围仅限于当前方法。
-
局部内部类访问外部类当前方法中的局部变量时,因无法保障变量的生命周期与自身相同,变量必须修饰为final。
-
限制类的适用范围(只能在当前方法中使用)
-
package part; public class TestOuter { public static void main(String[] args) { Outer outer = new Outer(); outer.show(); } }package part; // 外部类 public class Outer { private String name = "刘德华"; private int age = 35 ; public void show(){ // 定义局部变量 String address = "深圳"; // 局部内部类:注意不能加任何访问修饰符 class Inner{ private String phone = "123456"; private String email = "123456@qq.com"; public void show2(){ // 访问外部类的属性 System.out.println(name);// 也可以写Outer.this.name System.out.println(age); // 也可以写Outer.this.age // 访问内部类属性 System.out.println(phone); // 也可以写this.phone System.out.println(email);// 也可以写this.email // 访问局部变量,从JDK1.7开始,要求变量必须是常量final,而JDK1.8之后自动添加final。 System.out.println(address); } } // 创建局部内部类对象 Inner inner = new Inner(); inner.show2(); } }
-
匿名内部类
-
没有类名的局部内部类(一切特征都与局部内部类相同)。
-
必须继承一个父类或者实现一个接口。
-
package anonymous; public class TestUsb { public static void main(String[] args) { // 创建接口类型的变量 /* Usb usb = new Mouse(); usb.service(); */ class Fan implements Usb{ @Override public void service() { System.out.println("连接电脑成功,风扇开始工作了。。"); } } // 使用局部内部类创建对象 Usb usb = new Fan(); usb.service(); // 使用匿名内部类优化(相当于创建了一个局部内部类) Usb usb1 = new Usb() { @Override public void service() { System.out.println("连接电脑成功,风扇开始工作了。。"); } }; usb1.service(); } }package anonymous; // 接口 public interface Usb { void service(); }package anonymous; public class Mouse implements Usb { @Override public void service() { System.out.println("连接成功,鼠标开始工作了"); } }
-
-
定义类、实现类、创建对象的语法合并,只能创建一个该类的对象。
-
优点:减少代码量。
-
缺点:可读性较差。
Object类
-
超类、基类,所有类的直接或间接父类,位于继承树的最顶层。
-
任何类,如没有书写extends显示继承某个类,都默认直接继承Object类,否则为间接继承。
-
Object类中所定义的方法,是所有对象都具备的方法。
-
Object类型可以存储任何对象。
- 作为参数,可接受任何对象。
- 作为返回值,可返回任何对象。
-
getClass()方法
-
public final Class<?> getClass(){}
-
返回引用中存储的实际对象类型。
-
应用:通常用于判断两个引用中实际存储对象类型是否一致。
-
package Object; public class TestStudent { public static void main(String[] args) { Student s1 = new Student("aaa",20); Student s2 = new Student("bbb",22); // 判 断 s1 和 s2 是 不 是 同 一 个 类 型 Class class1 = s1.getClass(); Class class2 = s2.getClass(); if (class1 == class2) { System.out.println("s1和s2属于同一各类型"); }else { System.out.println("s1和s2不属于同一各类型"); } } }package Object; 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; } }
-
-
-
hashCode()方法
-
public int hashCode() {}
-
返回该对象的哈希码值。
-
哈希值根据对象的地址或字符串或数字使用hash算法计算出来的int类型的数值。
-
一般情况下相同对象返回相同哈希码。
-
package Object; public class TestStudent { public static void main(String[] args) { // getClass()方法 Student s1 = new Student("aaa",20); Student s2 = new Student("bbb",22); System.out.println(s1.hashCode()); System.out.println(s2.hashCode()); Student s3 = s1; System.out.println(s3.hashCode()); } }
-
-
-
toString()方法
-
public String toString() {}
-
返回该对象的字符串表示(表现形式)。
-
可以根据程序需求覆盖该方法,如:展示对象各个属性值。
-
package Object; public class TestStudent { public static void main(String[] args) { // getClass()方法 Student s1 = new Student("aaa",20); Student s2 = new Student("bbb",22); System.out.println(s1.toString()); System.out.println(s2.toString()); } }package Object; public class Student { private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } public String toString(){ return name+":"+age; } }
-
-
-
equals()方法
-
public boolean equals(Object obj){} -
默认实现为(this == obj),比较两个对象地址是否相同。
-
可进行覆盖,比较两个对象的内容是否相同。
-
equals()方法覆盖步骤
- 比较两个引用是否指向同一个对象
- 判断obj是否为null。
- 判断两个引用指向的实际对象类型是否一致。
- 强制类型转换
- 依次比较各个属性值是否相同。
-
package Object; public class TestStudent { public static void main(String[] args) { // getClass()方法 Student s1 = new Student("aaa",20); Student s2 = new Student("bbb",22); // 判 断 s1 和 s2 是 不 是 同 一 个 类 型 // Class class1 = s1.getClass(); // Class class2 = s2.getClass(); // if (class1 == class2) { // System.out.println("s1和s2属于同一各类型"); // }else { // System.out.println("s1和s2不属于同一各类型"); // } // hashCode方法 // System.out.println(s1.hashCode()); // // System.out.println(s2.hashCode()); // // Student s3 = s1; // System.out.println(s3.hashCode()); //toString方法 System.out.println(s1.toString()); System.out.println(s2.toString()); // equals方法,判断两个对象是否相等 System.out.println(s1.equals(s2));//false(s1,s2对象地址不同) Student s4 = new Student("小明", 17); Student s5 = new Student("小明", 17); System.out.println(s4.equals(s5));//false(s4,s5对象地址不同) } }package Object; 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; } public String toString(){ return name+":"+age; } @Override public boolean equals(Object obj) { // 1.判断两个对象是否是同一个引用 if (this == obj){ return true; } // 2.判断obj是否为null if (obj == null) { return false; } // 3.判断是否是同一个类型 if (this.getClass()==obj.getClass()){ } // instanceof 判断对象是否是某种类型 if (obj instanceof Student){ // 4.强制类型转换 Student s = (Student)obj; // 5. 比较属性 if (this.name.equals(s.getName())&&this.age==s.getAge()) { return true; } } return false; } }
-
-

浙公网安备 33010602011771号