一、属性
二、方法
三、构造器
四、代码块
五、内部类
一个类的内部又完整的嵌套了另一个类结构。被嵌套的类称为内部类(inner class),嵌套其他类的类称为外部类(outer class)。
内部类最大的特点就是可以直接访问私有属性,并且可以体现类与类之间的包含关系
内部类的分类
- 定义在外部类局部位置上(比如方法内):
1)局部内部类(有类名)
2)匿名内部类(没有类名)【重点】 - 定义在外部类的成员位置上:
1)成员内部类(没用static修饰)
2)静态内部类(使用static修饰)
(一)局部内部类
局部内部类是定义在外部类的局部位置,比如方法中、代码块中,并且有类名。
使用细则:
- 内部类可以直接访问外部类的所有成员,包括私有的
- 外部类需要创建对象,再访问内部类成员(注意:必须在作用域内)
- 内部类不能添加访问修饰符,因为它相当于局部变量。局部变量是不能使用修饰符的,但是可以使用final修饰,因为局部变量也可以使用final
- 作用域:仅仅在定义它的方法或代码块中
- 外部其他类不能直接访问内部类
- 外部类和内部类的成员重名时,就近原则;若想访问外部类成员,可使用“外部类名.this.成员”
class Outer{
private int n1 = 100;
private void m2(){ }
//4.
public void m1(){
//3.
final class Inner{
private int n1 = 800;
public void f1(){
//1. 6.
System.out.println(n1);
m2();
System.out.println(Outer.this.n1);
}
}
//2.
Inner inner = new Inner();
inner.f1();
}
}
(二)匿名内部类
匿名内部类是定义在外部类的局部位置,比如方法中、代码块中,并且无类名。
引入匿名内部类的目的?
当想要实现接口、抽象类的方法或重写类的方法时,需要重新定义一个类,但是这个类只使用一次。为了简便,引入匿名内部类。
主要有三种类型:
- 基于接口的匿名内部类
- 基于类的匿名内部类
- 基于抽象类的匿名内部类
public class Hello {
public static void main(String[] args) {
new Outer().method();
}
}
class Outer{//外部类
private int n1 = 100;
public void method(){
//1.基于接口的匿名内部类
//tiger编译类型是IA,运行类型是匿名类
//我们虽然不写匿名类的类名,其实系统内部自动分配一个名字
//匿名类只能使用一次
IA tiger = new IA(){
@Override
public void cry() {
System.out.println("老虎叫唤");
}
};
tiger.cry();
//2.基于类的匿名内部类
//father编译类型是Father,运行类型是匿名类
Father father = new Father("jack"){
@Override
public void test() {
System.out.println("匿名内部类重写test方法");
}
};
father.test();
//3.基于抽象类的匿名内部类
//编译类型是Animal,运行类型是匿名类
//除了以上创建对象再调用,还可以直接创建调用
//这种写法 比较常用
new Animal(){
@Override
void eat() {
System.out.println("小狗吃骨头");
}
}.eat();
}
}
interface IA{//1.接口
public void cry();
}
class Father{//2.外部其他类
public Father(String name) {
System.out.println("接收到了"+ name);
}
public void test(){ }
}
abstract class Animal{//3.抽象类
void eat(){};
}
输出:
老虎叫唤
接收到了jack
匿名内部类重写test方法
小狗吃骨头
使用细则:
- 匿名内部类既是一个类的定义,也是一个对象;从语法上看,它既有定义类的特征,也有创建对象的特征,对前面代码分析可以看出这个特点,因此可以直接调用匿名内部类方法。
- 匿名类可以直接访问外部所有成员,包括私有
- 外部其他类不能访问匿名内部类
- 不能添加访问修饰符
- 作用域:方法、代码块中
- 外部类和内部类的成员重名时,就近原则;若想访问外部类成员,可使用“外部类名.this.成员”
(三)成员内部类
成员内部类在外部类的成员位置上,不使用static修饰
使用细则:
- 成员内部类直接访问外部类所有成员,包括私有
- 外部类创建对象,再访问
- 外部其他类可以访问内部成员类,方法如下
- 可以使用任意访问修饰符(public、private、默认、protected),因为它的地位就是一个成员
- 作用域:和外部类的其他成员一样
- 外部类和内部类的成员重名时,就近原则;若想访问外部类成员,可使用“外部类名.this.成员”
public class Hello {
public static void main(String[] args) {
Outer outer = new Outer();
//外部其他类访问成员内部类
//方式一:外部类对象new一个内部类
Outer.Inner inner1 = outer.new Inner();
//方式二:外部类编写一个方法返回成员内部类
Outer.Inner inner2 = outer.getInner();
//方式三:原理如方法一
Outer.Inner inner3 = new Outer().new Inner();
}
}
class Outer{//外部类
private int n1 = 100;
public class Inner{//成员内部类
public int n1 = 100;
public void say(){
System.out.println("成员内部类访问内部类属性n1:"+ n1);
System.out.println("成员内部类访问外部类属性n1:"+ Outer.this.n1);
}
}
public Inner getInner(){//返回一个成员内部类
return new Inner();
}
public void find(){//外部类使用成员内部类
Inner inner = new Inner();
inner.say();
}
}
(四)静态内部类
成员内部类在外部类的成员位置上,使用static修饰
使用细则:
- 静态内部类直接访问外部类所有静态成员,包括私有,不能访问非静态成员
- 外部类创建对象,再访问静态内部类
- 外部其他类可以访问内部成员类,方法如下
- 可以使用任意访问修饰符(public、private、默认、protected),因为它的地位就是一个成员
- 作用域:和外部类的其他成员一样
- 外部类和内部类的成员重名时,就近原则;若想访问外部类成员,可使用“外部类名.成员”(无this,因为要访问的成员就是静态的)
public class Hello {
public static void main(String[] args) {
//方式一:new 外部类.内部类
Outer.Inner inner1 = new Outer.Inner();
//方式二:外部类编写一个方法返回静态内部类
Outer.Inner inner2 = new Outer().getInner();
}
}
class Outer{//外部类
private static int n1 = 100;
public static class Inner{//静态内部类
public int n1 = 100;
public void say(){
System.out.println("成员内部类访问内部类属性n1:"+ n1);
System.out.println("成员内部类访问内部类属性n1:"+ Outer.n1);
}
}
public Inner getInner(){//返回一个静态内部类
return new Inner();
}
public void find(){//外部类使用静态内部类
Inner inner = new Inner();
inner.say();
}
}
特别说明
本文章是个人整理的学习笔记,参考b站韩顺平老师的课程(【零基础 快速学Java】韩顺平 零基础30天学会Java)。老师讲的非常好,有兴趣的可以去看一下。