版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
DAY13 内部类和Object类
内部类
概述
内部类:定义在一个类内部的类叫做内部类
语法:
class 外部类 {
//成员位置
实例变量
静态变量
实例方法
静态方法
//局部位置(局部变量的位置)
方法{
int a = 10;//局部变量
}
}
为什么会有内部类的结构?
人类{
私有 嘴
泌尿系统器官类
消化系统器官类
}
内部类的分类
成员内部类(实例成员)
位置:成员内部类的定义位置相当于类中的实例成员位置
定义语法:
class 外部类{
//内部类
class 内部类{
}
}
对象创建的语法:(成员内部类的对象必须依赖外部类的对象才能创建)
外部类类名 外部类对象名 = new 外部类类名();
外部类类名.内部类类名 内部类对象名 = 外部类对象名.new 内部类类名();
eg:
//1 创建外部类的对象
Outer outer = new Outer();
//2 通过外部类对象创建内部类对象
Outer.Inner inner = outer.new Inner();
特点:
1.编译之后也会生成单独的字节码文件
2.成员内部类可以访问外部类的私有成员,而不破坏封装
3.当成员内部类中的属性和方法和外部类中的属性和方法存在重名的情况,用 类名.this. 区别
4.成员内部类中不能定义静态成员(属性和方法)
案例1:
package cn.baizhi.day13;
public class Demo1 {
public static void main(String[] args) {
//1 创建外部类的对象
Outer outer = new Outer();
//2 通过外部类对象创建内部类对象
Outer.Inner inner = outer.new Inner();
}
}
// 定义外部类
class Outer {
// 属性
private int a = 10;
int b = 20;
static int c = 30;
// 私有的方法
private void m2() {
}
// 静态方法
public static void m3() {
}
// 定义成员内部类
class Inner {
// 属性
int d = 40;
int a = 50;
// 方法
public void m1() {
System.out.println(a);// 访问外部类的私有成员变量
m2();// 访问私有的成员方法
System.out.println(c);
m3();
System.out.println(d);
}
}
}
案例2:关于重名的属性和方法区别
package cn.baizhi.day13;
public class Demo1 {
public static void main(String[] args) {
//1 创建外部类的对象
Outer outer = new Outer();
//2 通过外部类对象创建内部类对象
Outer.Inner inner = outer.new Inner();
inner.m1();
}
}
// 定义外部类
class Outer {
// 属性
private int a = 10;
// 定义成员内部类
class Inner {
// 属性
int a = 50;
// 方法
public void m1() {
//int a = 100;
/*System.out.println(a);// 访问外部类的私有成员变量 100
System.out.println(Inner.this.a);//50
System.out.println(Outer.this.a);//10
*/
//Inner.this.m2();
Outer.this.m2();
}
public void m2() {
System.out.println("内部类的m2");
}
}
public void m2() {
System.out.println("外部类的m2");
}
}
案例 3:关于成员内部类中是否能定义静态的成员
package cn.baizhi.day13;
public class Demo1 {
public static void main(String[] args) {
//1 创建外部类的对象
Outer outer = new Outer();
//2 通过外部类对象创建内部类对象
Outer.Inner inner = outer.new Inner();
}
}
// 定义外部类
class Outer {
// 定义成员内部类
class Inner {
//类变量
//static int a = 20;
//静态方法
public static void m1() {
}
}
}
静态内部类(静态成员)
位置:静态内部类和类中的静态成员地位相当
语法:
class 外部类{
static class 静态内部类类名{
}
}
对象创建的语法:静态内部类的对象不需要通过外部类对象创建
eg:
//创建对象
Outer.Inner inner = new Outer.Inner();
特点:
1.编译之后也会生成单独的class文件
2.静态内部类只能直接访问外部类的静态成员(属性和方法),不能直接访问外部类的非静态成员,如果非要访问,必须通过创建对象访问
3.当静态内部类和外部类静态成员重名,可以直接通过 类名. 解决
案例1:关于静态内部类能够访问外部类的哪些成员
package cn.baizhi.day13;
public class Demo1 {
public static void main(String[] args) {
//创建对象
Outer.Inner inner = new Outer.Inner();
}
}
// 定义外部类
class Outer {
//属性
int a = 10;//实例变量
static int b =20;//静态变量
//实例方法
public void m1() {
System.out.println("外部类的实例方法m1");
}
//静态方法
public static void m2() {
System.out.println("外部类的静态方法m2");
}
//定义静态内部类
static class Inner{
public void m3() {
//System.out.println(a);
//m1();
Outer outer = new Outer();
System.out.println(outer.a);
outer.m1();
System.out.println(b);
m2();
}
}
}
案例2:关于静态成员重名问题
package cn.baizhi.day13;
public class Demo1 {
public static void main(String[] args) {
//创建对象
Outer.Inner inner = new Outer.Inner();
inner.m3();
}
}
// 定义外部类
class Outer {
//属性
int a = 10;//实例变量
static int b =20;//静态变量
//实例方法
public void m1() {
System.out.println("外部类的实例方法m1");
}
//静态方法
public static void m2() {
System.out.println("外部类的静态方法m2");
}
//定义静态内部类
static class Inner{
//实例变量
//int a = 30;
static int b = 40;
public void m3() {
/*System.out.println(a);
//m1();
Outer outer = new Outer();
System.out.println(outer.a);
outer.m1();*/
/*System.out.println(Inner.b);
System.out.println(Outer.b);*/
Outer.m2();
}
public static void m2() {
System.out.println("内部类的静态方法m2");
}
}
}
局部内部类(局部变量的位置)
位置:局部内部类定义在外部类的方法中 相当于局部变量的位置 见案例1
语法:
class 外部类{
public void m(){
class 内部类{
}
}
}
特点:
1.也可以生成独立的class文件
2.局部内部类中不可以定义静态的成员
3.在局部内部类中可以直接访问外部的成员(静态成员和实例成员)
4.局部内部类中可以访问外部类的局部变量,但是必须要求外部类的局部变量是final修饰的 jdk8起 默认添加final
案例1:关于局部内部类对象创建的方式
// 定义外部类
class Outer {
public void m1() {
// 定义一个局部内部类
class Inner {
}
// 创建对象
Inner inner = new Inner();
}
/*
* public static void m2() { class Inner {
*
* } }
*/
}
案例:关于访问哪些成员
package cn.baizhi.day13;
public class Demo1 {
public static void main(String[] args) {
}
}
// 定义外部类
class Outer {
//属性
int a = 10;
static int b =20;
public void m3() {
}
public static void m4() {
}
public void m1() {
// 定义一个局部内部类
class Inner {
//static int c = 30;//不能定义静态的属性
int c = 30;
//方法
public void m2() {
System.out.println(a);
System.out.println(b);
m3();
m4();
}
/*public static void m3() {
}*///不能定义静态方法
}
// 创建对象
//Inner inner = new Inner();
}
/*
* public static void m2() { class Inner {
*
* } }
*/
}
案例:局部内部类访问外部类的局部变量
package cn.baizhi.day13;
public class Demo1 {
public static void main(String[] args) {
Outer outer = new Outer();
outer.m1();
}
}
// 定义外部类
class Outer {
public void m1() {
//定义一个外部类的局部变量
final int a = 30;
// 定义一个局部内部类
class Inner {
public void m2() {
System.out.println(a);//a的照片
}
}
//创建局部内部类的对象
Inner inner = new Inner();
inner.m2();
}
}
练习:
教学的接口
教学的方法
学校类
方法:为学生提供老师教学的方法
刘洋类 实现教学的接口
高健类 实现教学的接口
代码:
package cn.baizhi.day13;
import java.util.Scanner;
public class Demo2 {
public static void main(String[] args) {
//通过学校获取老师--正当途径
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个整数:");
int i = scanner.nextInt();
Teach teacher = School.getTeacher(i);
teacher.teach();
//开辅导班
/*LiuYang liuYang = new LiuYang();
liuYang.teach();*/
}
}
//定义一个接口
interface Teach{
void teach();
}
//定义一个学校类
class School {
//定义一个方法
public static Teach getTeacher(int i) {
//定义高健
class GaoJian implements Teach{
@Override
public void teach() {
System.out.println("高健教 抽烟 喝酒 大保健");
}
}
//刘洋
class LiuYang implements Teach{
@Override
public void teach() {
System.out.println("刘洋教java");
}
}
//当i为奇数返回高健 反之 返回刘洋
if (i%2==0) {
return new LiuYang();
} else {
return new GaoJian();
}
}
}
匿名内部类(特殊的局部内部类)
匿名内部类:是一个特殊的局部内部类,当一个类实现了一个接口或者继承了一个类的时候可以写成匿名内部类的形式
语法:看下边的案例
特点:匿名内部类只能使用一次去创建对象
案例:
package cn.baizhi.day13;
import java.util.Scanner;
public class Demo2 {
public static void main(String[] args) {
//通过学校获取老师--正当途径
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个整数:");
int i = scanner.nextInt();
Teach teacher = School.getTeacher(i);
teacher.teach();
//开辅导班
/*LiuYang liuYang = new LiuYang();
liuYang.teach();*/
}
}
//定义一个接口
interface Teach{
void teach();
}
//定义一个学校类
class School {
//定义一个方法
public static Teach getTeacher(int i) {
//当i为奇数返回高健 反之 返回刘洋
if (i%2==0) {
return new Teach(){
@Override
public void teach() {
System.out.println("刘洋教java");
}
};
} else {
return new Teach() {
@Override
public void teach() {
System.out.println("抽烟 喝酒 烫头");
}
};
}
}
}
案例:
package cn.baizhi.day13;
import java.util.Scanner;
public class Demo2 {
public static void main(String[] args) {
//通过学校获取老师--正当途径
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个整数:");
int i = scanner.nextInt();
Teach teacher = School.getTeacher(i);
teacher.teach();
//开辅导班
/*LiuYang liuYang = new LiuYang();
liuYang.teach();*/
}
}
//定义一个接口
interface Teach{
void teach();
}
//定义一个学校类
class School {
//定义一个方法
public static Teach getTeacher(int i) {
//定义高健
class GaoJian implements Teach{
@Override
public void teach() {
System.out.println("高健教 抽烟 喝酒 大保健");
}
}
//刘洋
class LiuYang implements Teach{
@Override
public void teach() {
System.out.println("刘洋教java");
}
}
//
/*class (假装没有名字) implements Teach{
@Override
public void teach() {
System.out.println("刘洋教java");
}
}*/
//当i为奇数返回高健 反之 返回刘洋
if (i%2==0) {
return new Teach(){
@Override
public void teach() {
System.out.println("java");
}
};
} else {
return new GaoJian();
}
}
}
Object类
学习方法:要学会自己学习研究,API 要学会自己查到应用
Object:是所有类的顶级父类 超类 基类 相当于人类的中类人猿 女娲 上帝类
Object类型的引用可以指向任何类型的对象
protected void finalize():当垃圾回收时会调用这个方法,标志着垃圾回收器回收垃圾
垃圾:当一个对象没有任何的引用指向的时候,这个对象就成为垃圾
Student student = new Student();
student = null;
垃圾回收:Java中有自己的垃圾回收机制
自动进行垃圾回收:当垃圾达到一定值的时候,垃圾回收机制会自动的回收垃圾
手动垃圾回收:可以通过代码通知垃圾回收器进行垃圾回收,但是垃圾回收器不一定进行垃圾回收,不一定管用
案例:自动垃圾回收
package cn.baizhi.day13;
public class Demo5 {
public static void main(String[] args) {
for (int i = 0; i < 10000000; i++) {
new Student();
}
}
}
class Student extends Object{
public void finalize() throws Throwable {
super.finalize();
System.out.println("垃圾被回收了");
}
}
案例:
package cn.baizhi.day13;
public class Demo5 {
public static void main(String[] args) {
Student student = new Student();
student = null;
System.gc();//负责通知进行垃圾回收
System.out.println("程序运行完毕");
}
}
class Student extends Object{
public void finalize() throws Throwable {
super.finalize();
System.out.println("垃圾被回收了");
}
}
toString 方法:打印对象的字符串形式,当打印一个对象的引用时会默认调用toString方法(必会的)
案例:
package cn.baizhi.day13;
public class Demo5 {
public static void main(String[] args) {
Student student = new Student("刘洋",17);
System.out.println(student);
Object object = new Student("高健", 250);
System.out.println(object);
Object[] object2 = {
new Student("赵四", 34),
new Wo(),
new Worker()
};
}
}
class Student extends Object{
String name;
int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
//重写toString
@Override
public String toString() {
return "name:"+this.name+"--- age:"+this.age;
}
}
class Wo{
}
getClass():通过类的对象能够返回类对象
案例:
package cn.baizhi.day13;
public class Demo5 {
public static void main(String[] args) {
//创建一个学生对象
//学生类的对象
Student student1 = new Student();
System.out.println(student1.hashCode());
//通过学生类的对象获取学生类类对象
Class c1 = student1.getClass();
System.out.println(c1.toString());
Student student2 = new Student();
System.out.println(student2.hashCode());
Class c2 = student2.getClass();
System.out.println("============================");
System.out.println(c1.hashCode());
System.out.println(c2.hashCode());
System.out.println(c1==c2);
}
}
class Student extends Object{
String name;
int age;
}
案例:
package cn.baizhi.day13;
public class Demo5 {
public static void main(String[] args) {
Animal animal1 = new Dog();
Animal animal2 = new Cat();
System.out.println(animal1.getClass());
System.out.println(animal2.getClass());
System.out.println(animal1.getClass() == animal2.getClass());
System.out.println(animal1 instanceof Dog && animal2 instanceof Dog);
}
}
class Student extends Object{
}
class Animal{
}
class Dog extends Animal{
}
class Cat extends Animal{
}
interface IA{
}
equals:判断两个对象的内容是否相同
equals方法的重写步骤:
1.判断 this 和obj地址是否相同
2.判断obj是否为空
3.判断是否是同类
4.向下转型
5.根据需求判断两个对象的属性是否相同
注意:第2和3两步不能颠倒 否则会出现空指针异常
案例:
package cn.baizhi.day13;
public class Demo5 {
public static void main(String[] args) {
//创建两个学生对象
Student student1 = new Student("高健", 250,"250250");
Student student2 = new Student("刘洋", 16,"888888");
Student student3 = new Student("高健", 25,"250250");
//1
//简单的数据类型==比较的的数值是否相同
/*int a = 10;
int b =11;
System.out.println(a==b);*/
//当两个学生的年龄相同 就认为是同一个人
/*System.out.println(student1==student3);
System.out.println(student1.equals(student3));*/
//试验一下字符串是否重写了equals
/*String string1 = new String("高健");
String string2 = new String("高健");
System.out.println(string1==string2);//false
System.out.println(string1.equals(string2));//true
*/
//当三个属性都相同才为同一个对象
System.out.println(student1.equals(student3));
}
}
class Student extends Object{
String name;
int age;
String id;
public Student() {
}
public Student(String name,int age,String id) {
this.name = name;
this.age = age;
this.id = id;
}
@Override
public boolean equals(Object obj) {
//向下转型
Student student = (Student) obj;
//判断
if (this.name.equals(student.name)&& this.age==student.age && this.id.equals(student.id)) {
return true;
} else {
return false;
}
}
}
案例:
package cn.baizhi.day13;
public class Demo5 {
public static void main(String[] args) {
// 创建两个学生对象
Student student1 = new Student("高健", 250, "250250");
Student student3 = null;
// Dog dog = new Dog();
// 当三个属性都相同才为同一个对象
System.out.println(student1.equals(student3));
// 1 当两个引用中存放的是同一个地址 直接就可以返回true
// 2 当 student3 = null
// 简单的数据类型==比较的的数值是否相同
/*
* int a = 10; int b =11; System.out.println(a==b);
*/
// 当两个学生的年龄相同 就认为是同一个人
/*
* System.out.println(student1==student3);
* System.out.println(student1.equals(student3));
*/
// 试验一下字符串是否重写了equals
/*
* String string1 = new String("高健"); String string2 = new String("高健");
* System.out.println(string1==string2);//false
* System.out.println(string1.equals(string2));//true
*/
}
}
class Student extends Object {
String name;
int age;
String id;
public Student() {
}
public Student(String name, int age, String id) {
this.name = name;
this.age = age;
this.id = id;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
/*
* @Override public boolean equals(Object obj) { if (this == obj) return
* true; if (obj == null) return false; if (getClass() != obj.getClass())
* return false; Student other = (Student) obj; if (age != other.age) return
* false; if (id == null) { if (other.id != null) return false; } else if
* (!id.equals(other.id)) return false; if (name == null) { if (other.name
* != null) return false; } else if (!name.equals(other.name)) return false;
* return true; }
*/
/*
* @Override public boolean equals(Object obj) {
*
* //1.当两个引用 this obj 地址相同直接就返回true if (this == obj) { return true; }
*
* //2 进行非空判断 if (obj==null||this==null) { return false; } //3 if
* (this.getClass()!=obj.getClass()) { return false; } //向下转型 Student
* student = (Student) obj;
*
* //判断 if (this.name.equals(student.name)&& this.age==student.age &&
* this.id.equals(student.id)) { return true; } else { return false; } }
*/
@Override
public boolean equals(Object obj) {
// 1 当this 和 obj 地址相同返回true
if (this == obj) {
return true;
}
// 2 当obj==null false
if (obj == null) {
return false;
}
// 3 判断两个对象的类型是否为同一个类型
if (this.getClass() != obj.getClass()) {
return false;
}
// 4 向下转型
Student student = (Student) obj;
// 5 根据开发需求 通过属性判断两个对象是否是同一个对象
if (this.name.equals(student.name) && this.age == student.age
&& this.id.equals(student.id)) {
return true;
} else {
return false;
}
}
}
class Dog {
}
总结
重点:
toString
equals
面试题:
== 和 equals区别
答:简单数据类型判断的都是数值,引用数据类型在重写之前是一样的都是判断的是地址值,重写之后判断的是两个对象的内容是否相同,从而得到两个对象是否是同一个对象
finalize()方法和getClass()了解
作业
1 7 8 9 26 除去String和包装类 全做
必做作业:以下的代码 手写10遍
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", id=" + id + "]";
}
@Override
public boolean equals(Object obj) {
// 1 当this 和 obj 地址相同返回true
if (this == obj) {
return true;
}
// 2 当obj==null false
if (obj == null) {
return false;
}
// 3 判断两个对象的类型是否为同一个类型
if (this.getClass() != obj.getClass()) {
return false;
}
// 4 向下转型
Student student = (Student) obj;
// 5 根据开发需求 通过属性判断两个对象是否是同一个对象
if (this.name.equals(student.name) && this.age == student.age
&& this.id.equals(student.id)) {
return true;
} else {
return false;
}
}
1.
package cn.baizhi.day13;
public class Demo3 {
public static void main(String[] args) {
//灯泡 接口的实现者
/*class Red implements LuoWen{
@Override
public void shine() {
System.out.println("发红光");
}
}
class Green implements LuoWen{
@Override
public void shine() {
// TODO Auto-generated method stub
System.out.println("发绿光");
}
}
//定义一个匿名的局部内部类
class (假装没有名字) implements LuoWen{
public void shine() {
// TODO Auto-generated method stub
System.out.println("发黄光");
}
}*/
//买一个台灯
Lamp lamp = new Lamp();
//买一个灯泡
//Green green = new Green();
//将灯泡安到台灯上并打开通电
lamp.on(new LuoWen(){
public void shine() {
// TODO Auto-generated method stub
System.out.println("发黄光");
}
});
lamp.on(new LuoWen() {
@Override
public void shine() {
// TODO Auto-generated method stub
System.out.println("发绿光");
}
});
}
}
//定义一个接口
interface LuoWen{
//通电
void shine();
}
class Lamp{//接口的使用者
//开关
public void on(LuoWen luoWen) {
luoWen.shine();
}
}
26.
package cn.baizhi.day13;
public class Demo4 {
public static void main(String[] args) {
Inter inter = MyClass.method();
inter.show();
}
}
//定义一个接口
interface Inter{
void show();
}
//定义一个类
class MyClass{
//代码
//返回一个inter接口的实现类对象
public static Inter method() {
Inter inter = new Inter() {
@Override
public void show() {
System.out.println("hello world");
}
};
return inter;
}
}