文章目录
1. 内部类的定义与使用
外部类只能用public和default默认修饰符,但内部类四种修饰符都可以用
1.1 基本概念
所谓内部类就是在一个类的内部嵌套其他类结构
// 定义一个外部类
class Outter{
private String title="i am class Outters title";
// 在外部类的内部定义一个内部类
class Inner{
//在内部类中定义一个普通方法
public void print(){
//调用外部类的private属性
System.out.println(title);
}
}
//在外部类定义一个方法,负责产生内部类对象以及调用内部类的print方法
public void fun(){
Inner inner=new Inner(); //内部类对象
inner.print(); // 内部类提供的print方法
}
}
public class Test {
public static void main(String[] args) {
Outter outter=new Outter(); //外部类的对象
outter.fun(); //外部类的方法
}
}
看完上述代码,我们的第一感受就是麻烦!确实,引入内部类让程序的结构变得复杂,但是内部类也有它的好处,就是我们可以方便的操作外部类的私有访问。
做个练习,我们在不修改主代码的情况下,对上述代码修改,使其也能达到上面的效果
class Outter{
private String title="i am class Outters title";
public String getTitle(){
return title;
}
public void fun(){
Inner inner =new Inner(this);
inner.print();
}
}
class Inner{
private Outter out;
public Inner(Outter out){
this.out=out;
}
public void print(){
System.out.println(out.getTitle());
}
}
public class Test {
public static void main(String[] args) {
Outter outter=new Outter();
outter.fun();
}
}
1.2 内部类为什么存在
- 内部类可以访问该类定义所在操作域的所有数据,包括私有操作域
- 内部类可以对该包下的其他类隐藏
- 内部类可以“破解”java单继承的缺陷
看个内部类“实现多继承”的例子
class food{
private String name="food的私有属性";
public String getName(){
return name;
}
}
class pureFood{
private int price=10;
public int getPrice(){
return price;
}
}
class Out{
//内部类
public class InnerClassFood extends food{
public String getName(){
return super.getName();
}
}
public class InnerClassPurFood extends pureFood{
public int getPrice(){
return super.getPrice();
}
}
//外部方法
public String getName(){
InnerClassFood innerClassFood=new InnerClassFood();
return innerClassFood.getName();
}
public int getPrice(){
InnerClassPurFood innerClassPurFood=new InnerClassPurFood();
return innerClassPurFood.getPrice();
}
}
public class Test1 {
public static void main(String[] args) {
Out out=new Out();
System.out.println(out.getName());
System.out.println(out.getPrice());
}
}
这里我们只是利用了内部类,在一个类内部建了两个内部类用来继承两个类,实现了所谓的“多继承”,但我们要记住,java是没有多继承的!
1.3 内部类与外部类的关系
- 静态内部类只能访问外部类的静态属性,要访问外部类的其他属性需要通过创建对象
- 成员内部类可以访问外部类的所有属性
- 外部类可以通过(静态内部类)内部类的对象,去访问内部类的所有属性(包括private属性),对于静态内部类:外部类也可以直接通过
类名.静态属性名
的方式----->访问静态内部类的静态属性,但是需要外部类.静态内部类.属性名
new Outer.StaticInner().静态属性。 - 成员内部类不能拥有static属性,静态内部类可以拥有所以修饰符的属性
- 其他类可以和new静态内部类,但不能直接new成员内部类。
2. 内部类
2.1、内部类的分类
- 成员内部类
- 静态内部类
- 方法内部类
- 匿名内部类
2.2、成员内部类
上面都是成员内部类
定义在类内部的类,与类的方法,属性属于同一级别的,即也是外部类的成员。
我们上面写的其实都是成员内部类。不做赘述,只需要注意两点:
成员内部类中不能存在任何static成员与方法
成员内部类的创建要依赖于外部类,没有外部类就没有内部类
2.3、静态内部类
静态内部类是用static修饰的内部类 。我们直到静态内部类与非静态内部类最大的区别是非静态内部类在编译完成之后会有一个隐含的引用,这个引用指向了创造它的外部类,而静态内部类是没有这个引用的,没有这个引用意味着:
- 静态内部类的创建不依赖于外部类,可以直接创建
- 静态内部类不可以使用外部类中的任何非静态属性和方法,而非静态内部类可以
外部类的创建语法:
2.4、方法内部类
方法内部类是定义在外部类的方法中,和成员内部类基本一致,只是作用域不用。方法内部类只能在该方法中被引用,出了该方法的作用域就会失效。方法内部类一般用于解决复杂问题的系统,想创建一个类来辅助我们解决方案,但又不希望这个类是公共的,因此就有了方法内部类。
方法内部类有几点需要注意的:
- 方法内部类不允许使用权限修饰符,public、protected、private均不允许
- 方法内部类对外完全隐藏,除了创建这个类的方法可以访问外,别的都不可以访问
- 局部内部类要想使用方法形参,该参数必须为final声明的(JDK1.8之后隐式final声明)
class Outter{
private int num = 10;
public void test(int num2){
class Inner{
public void fun(){
num += 20;
System.out.println(num);
// 对num2进行改变会报错
// 因为方法内部类接收外部参数必须是final的,不可修改的
System.out.println(num2);
}
}
new Inner().fun();
}
}
public class Test{
public static void main(String[] args) {
Outter outter = new Outter();
outter.test(20);
}
}
2.5、匿名内部类
- 匿名内部类必须继承一个抽象类或者实现一个接口
- 匿名内部类没有构造方法,因为他没有类名。
- 匿名内部类没有访问修饰符
- 匿名内部类中不能存在任何静态成员或方法
- 与局部内部相同,匿名内部类也可以引用方法形参,此形参也必须声明为final
class MyInterface{
void test() {
System.out.println("MyInterface's test method ");
}
}
class Outter{
private int num = 10;
public void test(int testNum){
new MyInterface(){
@Override
void test() {
System.out.println("i am no-name InnerClass");
System.out.println(testNum);
}
}.test();
}
}
public class Test{
public static void main(String[] args) {
Outter outter = new Outter();
outter.test(100);
}
}