1.内部类概述和访问特点
-
内部类:就是在类内部再声明类
-
内部类访问特点
1.内部类可以直接访问外部类的成员,包括私有。
2.外部类要访问内部类的成员,必须创建对象。 -
内部类对象的创建语法
1.外部类名.内部类名 对象名 = 外部类对象.内部类对象;
2.开发中自己声明个内部类比较少用,用的多的就是集合中的遍历
2.内部类的创建
- 在外部类内部创建:
和创建普通对象一样
Inner inner = new Inner();
- 在外部类外部(也就是其他类)创建静态内部类:
外部类.内部类 内部类对象 = new 外部类.内部类();
//外部类.内部类 内部类对象 = new 外部类.内部类();
Outer.Inner inner = new Outer.Inner();
- 在外部类外部创建非静态内部类:
外部类.内部类 内部类对象 = new 外部类().new 内部类();
//外部类.内部类 内部类对象 = new 外部类().new 内部类();
Outer.Inner inner = new Outer().new Inner();
3.内部类分类
成员内部类
- 顾名思义,相当于外部类的一个成员,成员内部类内部不允许存在任何 static 变量或方法;
public class Tset01 {
public static void main(String[] args) {
Outer.Inner inner = new Outer().new Inner();
inner.test();
}
}
class Outer {
private String str1 = "private...";
public String str2 = "public...";
class Inner {
// public static String str3 = "static..."; //报错
public void test() {//可访问外部属性,方法
System.out.println(str1);
System.out.println(str2);
}
}
}
- 内部类问题:
//要求:使用已知的变量,在控制台输出30,20,10。
class Outer {
public int num = 10;
class Inner {
public int num = 20;
public void show() {
int num = 30;
System.out.println(num);
System.out.println(this.num);
System.out.println(Outer.this.num);
}
}
}
class Test {
public static void main(String[] args) {
Outer.Inner inner = new Outer().new Inner();
inner.show();
}
}
局部内部类
类似于局部变量,是存在于方法内的类(方法内部类)
- 该内部类不能用访问权限修饰符(public、private、protected 均不允许);
- 局部内部类对外部完全隐藏,除了创建这个类的方法可以访问它以外,其他地方均不能访问,也就是说如果该方法没有创建对象并调用,那这个内部类就废了;
- 局部内部类访问局部变量必须用final修饰
public class Tset01 {
public static void main(String[] args) {
Outer outer = new Outer();
outer.test1();
}
}
class Outer {
public void test1() {
final int a = 10;//局部变量
class Inner {//局部内部类
public void test2() {
System.out.println(a);
}
}
Inner inner = new Inner();
inner.test2();
}
}
代码内存图:
- 局部内部类在访问他所在方法中的局部变量必须用final修饰,为什么?
因为当调用这个方法时,局部变量如果没有用final修饰,他的生命周期和方法的生命周期是一样的,当方法弹栈,这个局部变量也会消失,那么如果局部内部类对象还没有马上消失想用这个局部变量,就没有了,如果用final修饰会在类加载的时候进入常量池,即使方法弹栈,常量池的常量还在,也可以继续使用
(JDK8不用写final,不报错)
私有内部类的使用【了解】
public class Tset01 {
public static void main(String[] args) {
Outer out = new Outer();
out.test1();//输出 Inter test2......
}
}
class Outer{
int n = 10;
private class Inner{
//n = 20; //不能访问,报错
public void test2(){
System.out.println("Inter test2......");
}
}
public void test1(){
Inner a = new Inner();
a.test2();
}
}
静态内部类的使用 【了解】
- 成员内部类被静态修饰后的访问方式是:
外部类名.内部类名 对象名 = 外部类名.内部类对象;
public class Tset01 {
public static void main(String[] args) {
Outer.Inner inner = new Outer.Inner();
inner.test(); //输出:Inner test...
Outer.Inner1.test();//输出:Inner1 test...
}
}
class Outer {
static class Inner {
public void test() {
System.out.println("Inner test...");
}
}
static class Inner1 {
public static void test() {
System.out.println("Inner1 test...");
}
}
}
匿名内部类
-
匿名内部类就是内部类的简化写法,是一个没有名字的方法内部类,特点和方法与方法内部类完全一致。
-
写匿名内部类前提是存在一个抽象类或者接口
匿名内部类没有类名,因此没有构造方法。 -
匿名内部类格式:
new 抽象类或者接口名(){ 重写方法; } -
匿名内部类本质是什么呢?
是一个继承了该类或者实现了该接口的子类匿名对象。 -
匿名内部类的特点
匿名内部类必须实现接口的所有方法
匿名内部类必须实现抽象类的所有方法 -
匿名内部类的方法调用
像普通对象一样,调用方法即可
public class Tset01 {
public static void main(String[] args) {
//匿名内部类,就相当于是抽象类的子类
new Inner() {//匿名内部类,实现所有抽象方法
@Override
public void test() {
// TODO Auto-generated method stub
System.out.println("匿名内部类 ...");
}
}.test();
//也可以将匿名类赋给对象,这样可以多次执行方法
Inner inner = new Inner() {
@Override
public void test() {
// TODO Auto-generated method stub
System.out.println("匿名内部类 ...1");
}
};
inner.test();
}
}
abstract class Inner{//抽象类
public abstract void test();
}
使用匿名内部类的代码补全:
//要求在控制台输出”HelloWorld”
interface Inner { void show(); }
class Outer { //补齐代码 }
class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
}
}
==========================================
class Outer { //补齐代码
public static Inner method() {
return new Inner() {
@Override
public void show() {
// TODO Auto-generated method stub
System.out.println("HelloWorld");
}
};
}
}