1.内部类
/**
* @author : sunkepeng E-mail:[email protected]
* @date : 2020/7/22 14:27
*
* 如果一个事物的内部包含另一个事物,那么这就是一个类内部包含另一个类。
* 例如:身体包含心脏,汽车包含发动机。。。
* 内部类必须在外部类内部才能正常使用
*--------------------------------------------------------------------
* 分类:
* 1.成员局部类
* 2.局部内部类(包含匿名内部类)
*=====================================================================
* a.
* 成员内部类定义格式:
* 修饰符 class 外部类名称 {
* 修饰符 class 内部类名称 {
* // TODO
* }
* // TODO
* }
* 注意事项:
* 内用外,随意访问;外用内,需要内部类对象。
* 使用方式:
* 1.间接方式:在外部类的方法当中,使用内部类;然后main只是调用外部类的方法
* 2.直接方式,公式:
*------>外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();
* ======================================================================
* b.
* 局部内部类定义格式:
* 修饰符 class 外部类名称(参数列表){
* 修饰符 返回值类型 外部方法名称(参数列表){
* class 局部内部类名称{
* // TODO
* }
* }
* }
* “局部”的意思是只有所属的方法可以使用,方法外不可用。
* 局部内部类如果希望访问所在方法的局部变量,那么这个局部变量必须是【有效final】的
* 备注:
* 从Java8开始,只要局部变量事实不变,那么final关键字可以shenglue。
* 原因:
* 1.new出来的对象在堆中
* 2.局部变量是跟着方法走的,在栈内存中
* 3.方法结束后,立刻出栈,局部变量就会消失
* 4.new出来的对象还会在堆中持续存在,直到垃圾回收为止
* ------------------------------------------------------------------------
* 修饰符使用范围:
* 1.外部类:public / (default)
* 2.成员内部类:public / protected / (default) / private
* 3.局部内部类:什么都不写
*/
public class InnerClass {
public static void main(String[] args) {
Body body = new Body();
// 通过外部类的对象,调用外部类的方法,外部类的方法间接使用内部类
body.methodBody();
System.out.println("=========================");
Body.Heart heart = new Body().new Heart();
heart.beat();
Outer.Inner obj = new Outer().new Inner();
obj.methodInner();
Outer2 outer2 = new Outer2();
outer2.methodOuter();
}
}
/**
* @author : sunkepeng E-mail:[email protected]
* @date : 2020/7/22 14:33
*
* 编译完输出文件:
* Body.class 外部类输出
* Body$Heart.class 内部类输出
*/
public class Body {
public class Heart {// 成员内部类
public void beat(){
System.out.println("心脏跳动");
System.out.println("我叫," + name);
}
}
// 外部类成员变量
private String name;
public void methodBody(){
System.out.println("外部类方法");
Heart heart = new Heart();
heart.beat();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* @author : sunkepeng E-mail:[email protected]
* @date : 2020/7/22 14:49
*
* 如果出现了重名现象,那么格式是:---> 外部类名称.this.外部类成员变量名
*/
public class Outer {
int num = 10;
public class Inner{
int num = 20;
public void methodInner(){
int num = 30;
System.out.println(num);
System.out.println(this.num);
System.out.println(Outer.this.num);
}
}
}
/**
* @author : sunkepeng E-mail:[email protected]
* @date : 2020/7/22 14:56
*/
public class Outer2 {
public void methodOuter(){
int num = 50;
// num = 20; // 错误写法
// 局部内部类任何修饰符都不能写
class Inner { // 局部内部类
// int num = 100;
public void methodInner(){
System.out.println(num);
}
}
Inner inner = new Inner();
inner.methodInner();
}
}
2.匿名内部类
/**
* @author : sunkepeng E-mail:[email protected]
* @date : 2020/7/22 15:58
*
* 如果接口的实现类(或者父类的子类),只需要使用唯一一次,
* 就可以省略类的定义,改为直接使用【匿名内部类】
*
* 匿名内部类格式:
* 接口名称 对象名 = new 接口名称(){
* // 覆盖重写接口中所有抽象方法
* };
* 格式中,大括号之间的是一个类,它没有名字,并且实现了接口中的抽象方法
* 好处:
* 为了使用接口,不得不针对接口做一个实现类,如果只使用一次,不想单独定义一个类---
* ---> 可以直接 new 接口(){}; 补充一个大括号,在大括号中实现一个没有名字的类,随用随定义
*
* 对格式 “new 接口名称() {...} 进行解析:
* 1.new 代表创建对象的动作
* 2.接口名称就是匿名内部类需要实现哪个接口的抽象方法
* 3.{...} 大括号之间的内容是匿名内部类的内容
*
* 注意几点问题:
* 1.匿名内部类在创建对象时,只能使用唯一一次,如果希望多次使用,需要单独定义实现类
* 2.匿名对象,在【调用方法】的时候,只能调用唯一一次
* 如果希望同一个对象,调用多次方法,那么必须给对象起一个名字
* 3.匿名内部类是省略了【实现类(或子类)】的名称
* 匿名对象是省略了【对象名称】
* 强调:二者不是同一回事
*/
public class MainTest {
public static void main(String[] args) {
MyInterfaceImpl impl = new MyInterfaceImpl();
impl.method1();
impl.method2();
System.out.println("=============");
MyInterface obj = new MyInterfaceImpl();
obj.method1();
obj.method2();
System.out.println("==============");
// 使用匿名内部类
// 匿名内部类,不是匿名对象,对象名字叫做 niMing
MyInterface niMing = new MyInterface() {
@Override
public void method1() {
System.out.println("匿名内部类实现的方法111-A");
}
@Override
public void method2() {
System.out.println("匿名内部类实现的方法222-A");
}
};
niMing.method1();
niMing.method2();
System.out.println("==============");
// 匿名内部类,同时是匿名对象
new MyInterface() {
@Override
public void method1() {
System.out.println("匿名内部类实现的方法111-B");
}
@Override
public void method2() {
System.out.println("匿名内部类实现的方法222-B");
}
}.method1();
new MyInterface() {
@Override
public void method1() {
System.out.println("匿名内部类实现的方法111-B");
}
@Override
public void method2() {
System.out.println("匿名内部类实现的方法222-B");
}
}.method2();
}
}
/**
* @author : sunkepeng E-mail:[email protected]
* @date : 2020/7/22 15:55
*/
public interface MyInterface {
void method1();
void method2();
}
/**
* @author : sunkepeng E-mail:[email protected]
* @date : 2020/7/22 15:56
*/
public class MyInterfaceImpl implements MyInterface{
@Override
public void method1() {
System.out.println("实现类覆盖重写了方法111");
}
@Override
public void method2() {
System.out.println("实现类覆盖重写了方法222");
}
}