1、介绍
package level2.interClass;
public class MyInterClass {
public static void main(String[] args) {
}
}
class Outer{
private int n1 = 100;
public Outer(int n1){
this.n1 = n1;
}
public void m1(){
System.out.println("m1()");
}
{
System.out.println("代码块...");
}
class Inner{ //内部类
}
}
2、局部内部类
package level2.interClass;
public class LocalInnerClass {
public static void main(String[] args) {
MyOuter myOuter = new MyOuter();
myOuter.m1();
}
}
class MyOuter{
private int n1=210;
public void m2(){
System.out.println("MyOuter m2()...");
}
public void m1(){
// 不能添加访问修饰符,但是可以使用final修饰
// 作用域仅仅在m1方法体内
final class MyInner{ // 本质仍是一个类
private int n1 = 900; // 内部类中含有同名的n1
public void f1(){
// 可以直接访问外部类的成员,包括私有属性
// 若内部类中含有同名成员,一般遵循就近原则,若指定访问外部类成员,需要 外部类名.this.成员:
// MyOuter.this 本质是外部类的对象,谁调用f1(),MyOuter.this就是谁
System.out.println("MyOuter n1=" + MyOuter.this.n1);
// 如无显式指定,则遵循就近原则
System.out.println("MyInner n1="+n1);
m2();
}
}
// 外部类访问内部类的成员,需要创建对象再访问
MyInner myInner = new MyInner();
myInner.f1();
// 若MyInner是public,则可以继承
// class MyInner01 extends MyInner{}
}
{
// 也可以在代码块中
class MyInner02{}
}
}
3、匿名内部类
package level2.interClass;
public class AnoymousInnerClass {
public static void main(String[] args) {
}
}
class Outer01{ //外部类
private int n1 = 10;
public void method() {
// 基于接口的匿名内部类
// 想使用IA接口中的方法,但是不想定义类和实例化对象
// 1)tiger的编译类型是 IA,运行类型是 匿名内部类
// 2)匿名内部类,代码在底层运行时,实际上会创建一个类去实现接口,且会分配一个类名: Outer01$1 (外部类+$i)
// 3)jdk底层在创建了匿名内部类Outer01$1,立即就创建了对象实例,并且返回地址
// 4)匿名内部类使用一次,就不能再使用,但是实例化出来的对象仍可以继续使用
// 5)匿名内部类是Outer01$1,tiger是对象
IA tiger = new IA() {
public void cry() {
System.out.println("老虎叫...");
}
};
System.out.println("tiger的运行类型 = " + tiger.getClass());
tiger.cry(); // 调用
// 基于类的匿名内部类
// 1) tiger的编译类型是 Father,运行类型是 Outer01$2
// 3) 同时返回一个对象
// 注意:参数列表也会传递给构造器
Father father = new Father("tom") {
@Override
public void test() {
System.out.println("匿名内部类重写了test方法");
}
};
System.out.println("father的运行类型 = " + father.getClass());
father.test();
// 注意: 以下形式 不带{} 是实例化对象
Father fa = new Father("tom");
}
}
class Outer02{
private int n1=100;
public void f1(){
// 第一种调用方式:对象调用
Person p = new Person(){
@Override
public void hi() {
System.out.println(" Outer02 中的 第1个hi");
}
};
p.hi();
// 第二种调用方式: 直接调用(可传参)
new Person(){
@Override
public void hi() {
System.out.println(" Outer02 中的 第2个hi");
}
}.hi();
}
}
class Person{
public void hi(){
System.out.println(" Person hi() ");
}
}
interface IA{ // 接口
public void cry();
}
class Father {
public Father(String name) { // 构造器
}
public void test() {
}
}
abstract class Animal{
abstract public void eat();
}
3.1、匿名内部类练习01
package level2.interClass;
public class InnerClassExercise {
public static void main(String[] args) {
// 将匿名内部类 作为参数传递
f1(new AA() {
@Override
public void show() {
System.out.println("f1() 中的show");
}
});
}
// 静态方法 形参是接口类型
public static void f1(AA aa){
aa.show();
}
}
interface AA{
void show();
}
3.2、匿名内部类练习02
package level2.interClass;
public class InnerClassExercise01 {
public static void main(String[] args) {
//
new CellPhone().alarmclock(new Bell() {
@Override
public void ring() {
System.out.println("懒猪起床了...");
}
});
CellPhone cellPhone = new CellPhone();
cellPhone.alarmclock(new Bell(){
@Override
public void ring() {
System.out.println("开始上课了...");
}
});
cellPhone.alarmclock(new Bell(){
@Override
public void ring() {
System.out.println("已经下课了...");
}
});
}
}
interface Bell{
public void ring();
}
class CellPhone{
public void alarmclock(Bell bell){
bell.ring();
}
}
4、成员内部类
package level2.interClass;
public class MemberInnerClass {
public static void main(String[] args) {
Outer03 outer03 = new Outer03();
outer03.f1();
// 外部其他类 使用成员内部类的2种方式
Outer03.Inner03 inner03 = outer03.new Inner03(); // 注意,这里outer03.new是: 对象实例.new 而非 类名Outer03.new
// 在外部类中写一个方法,可以返回一个 Inner03 的对象实例
Outer03.Inner03 inner031 = outer03.getInner();
//
}
}
class Outer03{
private int n1 = 10;
public String name = "张三";
// 成员内部类 是定义在外部类成员的位置
public class Inner03{
private int n2 = 20;
public void say(){
// 可以直接访问外部类的所有成员,包括私有的
System.out.println("n1=" + n1);
}
}
// 方法返回 Inner03 的实例
public Inner03 getInner(){
return new Inner03();
}
public void f1(){
// 使用成员内部类中的属性--> 先实例化对象,再调用方法
Inner03 inner03 = new Inner03();
inner03.say();
System.out.println(inner03.n2); // 可以直接调用属性
}
}
5、静态内部类
package level2.interClass;
public class StaticInnerClass {
public static void main(String[] args) {
Outer05 outer05 = new Outer05();
outer05.m1();
// 外部其他类 使用静态内部类
// 1. 静态内部类,可以通过类名直接访问
Outer05.Inner05 inner05 = new Outer05.Inner05();
inner05.say1();
// 在外部类中写一个方法,可以返回一个 Inner03 的对象实例
Outer05.Inner05 inner051 = outer05.getInner();
inner051.say1();
// 在外部类中写一个静态方法,可以返回一个 Inner03 的对象实例
Outer05.Inner05 inner052 = Outer05.getInner01();
inner052.say1();
}
}
class Outer05{
private int n1=10;
public static String name = "张三";
// 放在外部类的成员位置,有 static 修饰
public static class Inner05{
public void say1(){
System.out.println("name = " + name); // 不能直接访问n1
}
private void say(){
System.out.println("name = " + name); // 不能直接访问n1
}
}
public static Inner05 getInner01(){
return new Inner05();
}
public Inner05 getInner(){
return new Inner05();
}
public void m1(){
Inner05 inner05 = new Inner05();
inner05.say();
}
}



