内部类
内部类概念
什么是内部类
将类写在其他类的内部,可以写在其他类的成员位置和局部位置,这时写在其他类内部的类就称为内部类。其他类也称为外部类。
简单理解就是将一个类定义在另一个类里面,这样称为内部类(类中类)(套娃)
什么时候使用内部类
在描述事物时,若一个事物内部还包含其他可能包含的事物,比如在描述汽车时,汽车中还包含这发动机,这时发动机就可以使用内部类来描述。
示例1
class 机箱{ //外部类
class 硬盘{ //内部类
}
}
示例2
class 汽车 { //外部类
class 发动机 { //内部类
}
}
内部类分类
内部类分为:
1.成员内部类
2.局部内部类
3.静态内部类
4.匿名内部类
我们定义内部类时,就是一个正常定义类的过程,同样包含各种修饰符、继承与实现关系等。在内部类中可以直接访问外部类的所有成员。
成员内部类
成员内部类,定义在外部类中的成员位置。与类中的成员变量相似,可通过外部类对象进行访问
定义格式
class 外部类 {
修饰符 class 内部类 {
//其他代码
}
}
访问方式
成员内部类是依附外部类而存在的,也就 是说,如果要创建成员内部类,前提是必须存在一个外部类对象。
外部类名.内部类名 变量名 = new 外部类名().new 内部类名();
演示:
public class Test {
//内部类访问
public static void main(String[] args) {
// 创建内部类对象 (先有身体再有心脏)
Body.Heart bh = new Body().new Heart();
// 调用内部类中的方法
bh.jump();
}
}
//内部类定义
class Body {// 外部类,身体
class Heart { // 内部类,心脏
//创建内部类方法
public void jump() {
System.out.println("心脏在跳动");
}
}
}
结果:
心脏在跳动
成员内部类访问外部类成员
当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。
如果要访问外部类的同名成员,那么访问方式为:
外部类.this.成员变量
外部类.this.成员方法
public class Test {
public static void main(String[] args) {
Out.In in = new Out().new In();
in.show();
}
}
class Out {
//外部变量
int num = 10;
//外部方法
public void show2() {
System.out.println(num);
}
public class In {
//内部变量
int num = 20;
//内部方法
public void show() {
//访问外部类成员变量
System.out.println(Out.this.num);
//访问本类成员变量(内部类)
System.out.println(num);
}
}
}
结果:
10
20
成员内部类使用private修饰
成员内部类相当于外部类的一个成员被private修饰的成员不能直接访问,如果想要访问,那么怎么办?
按照封装成员变量的思想,提供外界访问方法即可
如何理解?
比如人的心脏,心脏生病了只能医生来访问,普通人是不能进行访问的
public class Test {
public static void main(String[] args) {
Body body = new Body();
body.jump();//调用身体的jump方法,再由Body进行控制
}
}
class Body {// 外部类,身体
private class Heart { // 内部类,心脏
public void jump() {
System.out.println("心脏在跳动");
}
}
//身体内部提供心脏对象
Heart heart = new Heart();
//身体内部提供获取心脏方法
public void jump() {
heart.jump();
}
}
结果:
心脏在跳动
局部内部类
局部内部类,是定义在外部类方法中的局部位置,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。
注意:局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的。
定义格式
class 外部类 {
修饰符 返回值类型 方法名(参数) {
class 内部类 {
//其他代码
}
}
}
访问方式
在内部类所在的法中,创建内部类对象,进行访问
public class Test {
public static void main(String[] args) {
//创建外部类对象
Out inn = new Out();
//访问外部类方法
inn.m1();
}
}
class Out {
public void m1() {
//局部内部类
class In {
public void show() {
System.out.println("show...");
}
}
//在m1方法中创建局部内部类对象,提供访问
In inner = new In();
inner.show();
}
}
结果:
show...
静态内部类
在类的前面多了一个关键字static。静态内部类是不需要依赖于外部类的,在没有外部类的对象的情况下,可以创建静态内部类的对象,静态内部类只能访问静态外部类成员
public class Test {
public static void main(String[] args) {
//因为静态修饰,所以In不需要用new
Out.In in = new Out.In();
in.show();
}
}
class Out {
private int num = 20;
private static int num2 = 10;
static public class In {
public void show() {
//错误,只能访问静态成员
//System.out.println(Out.this.num);
//访问静态,直接调用,不用加this
System.out.println(Out.num2);
}
}
}
结果:
10
匿名内部类
匿名对象概念:
匿名对象是指创建对象时,只有创建对象的语句,却没有把对象地址值赋值给某个变量。
例如
public class Person{
public void eat(){
System.out.println();
}
}
//创建一个普通对象
Person p = new Person();
//创建一个匿名对象
new Person();
匿名对象的特点
创建匿名对象直接使用,没有变量名。
new Person().eat(); //eat方法被一个没有名字的Person对象调用了。
匿名对象在没有指定其引用变量时,只能使用一次。
new Person().eat(); 创建一个匿名对象,调用eat方法
new Person().eat(); 想再次调用eat方法,重新创建了一个匿名对象
匿名对象可以作为方法接收的参数、方法返回值使用
class Test {
public static void main(String[] args) {
//调用getPerson方法,得到一个Person对象
Person person = One.getPerson();
//调用method方法
One.method(person);
//匿名对象作为方法接收的参数
One.method(new Person());
}
}
class Person{}
class One {
public static Person getPerson() {
//普通方式
//Person p = new Person();
//return p;
//匿名对象作为方法返回值
return new Person();
}
public static void method(Person person) {
System.out.println("玩游戏");
}
}
结果:
玩游戏
玩游戏
匿名内部类概念
最常用到的内部类就是匿名内部类,它是局部内部类的一种。
定义的匿名内部类有两个含义:
临时定义某一指定类型的子类
定义后即刻创建刚刚定义的这个子类的对象
本质:
是一个继承了该类或者实现了该接口的子类匿名对象
匿名内部类的作用与格式
作用:匿名内部类是创建某个类型子类对象的便捷方式。
格式:
new 父类或接口(){
//进行方法重写
};
示例:
//已经存在的父类:
public abstract class Person{
public abstract void eat();
}
//定义并创建该父类的子类对象,并用多态的方式赋值给父类引用变量
Person p = new Person(){
public void eat() {
System.out.println(“我吃了”);
}
};
//调用eat方法
p.eat();
使用匿名对象的方式,将定义子类与创建子类对象两个步骤由一个格式一次完成。
虽然是两个步骤,但是两个步骤是连在一起完成的。
匿名内部类如果不定义变量引用,则也是匿名对象。
//已经存在的父类:
public abstract class Person{
public abstract void eat();
}
//匿名调用
new Person(){
public void eat() {
System.out.println(“我吃了”);
}
}.eat();
演示:
class Test {
public static void main(String[] args) {
//如何调用PersonOne中的method方法呢?
//使用普通方式
//PersonOne po = new PersonOne();
//Person s = new Person();
//po.method(s);
//使用匿名对象
//new PersonOne().method(new Person());//里面传递的是一个抽象类的子类对象
/*
new Person(){
public void show(){
System.out.println("我爱学习");
}
};
上面代码相当于 new Person();
*/
//使用匿名内部类怎么做?
PersonOne po = new PersonOne();
po.method(new Person() {
public void show() {
System.out.println("我爱学习");
}
});//里面传递该类的子类匿名对象
}
}
//抽象类
abstract class Person {
public abstract void show();
}
class PersonOne {
public void method(Person p) {
p.show();
}
}
内部类应用场景
方法参数是类类型
调用方式:直接创建类的对象
方法是参数是抽象类型
调用方式:
1.创建该抽象类的子类对象
2.使用匿名内部类实现
方法参数是接口类型
调用方式:
1.创建该接口的实现类
2.使用匿名内部类