如果一个事物的内部包含另一个事物 那么这就是一个类内部包含另一个类
例如:身体和心脏的关系 又如:汽车和发动机的关系
分类:
1,成员内部类
2,局部内部类(包含匿名内部类)
成员内部类
/*
* 成员内部类的定义格式:
* 修饰符 class 类名称{
* 修饰符 class 类名称{
* //...
* }
* }
* 注意:内用外 随意使用
* 外用内,需要内部类对象
*
* ===================================
* 如何使用成员内部类
* 1,在外部类的方法当中 使用内部类 然后 main只调用外部类方法
* 2,直接方式:公式
* 外部类名称.内部类名称 对象名 =new 外部类名称().new 内部类名称()*/
public class Demo01InnerClass {
public static void main(String[] args) {
Body body=new Body();
body.methodBody();
Body.Heart heart=new Body().new Heart();
heart.beat();
}
}
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;
}
}
//如果出现了重名现象 那么格式:外部类名称.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);
}
}
}
局部内部类
public class DemoMain {
public static void main(String[] args) {
Outer obj=new Outer();
obj.methodOuter();
}
}
/*
* 如果一个类是定义在一个方法内部 那么这就是一个内部类
* 局部:只有当前这个所属的方法才能使用它 出了这个方法外面就不能用了
*
* 定义格式
* 修饰符 class 外部类名称{
* 修饰符 返回值类型 外部类方法名称(参数列表){
* class 局部内部类名称{
* //...
* }
* }
* }
*
* 小结:
* public>protected>default>private
* 1,外部类:public/default
* 2,成员内部类:public/protected/default/private
* 3,局部内部类;什么都不能写*/
public class Outer {
public void methodOuter(){
class Inner{
int num=10;
public void methodInner(){
System.out.println(num);
}
}
Inner inner=new Inner();
inner.methodInner();
}
}
局部内部类 如果希望访问所在方法的局部变量 那么这个局部变量必须是【有效的final】
从java8+开始 只要局部变量事实不变 那么final关键字可以省略
原因:
- 1,new出来的对象在堆内存当中
- 2,局部变量是跟着方法走的 在栈内存当中
- 3,方法运行结束之后 立刻出栈 局部变量就会立刻消失
- 4,但是new出来的对象会在堆当中持续存在 知道垃圾回收消失*/
public class MyOuter {
public void methodOuter(){
int num=10;
class MyInner{
public void methodInner(){
System.out.println(num);
}
}
}
}
小结:
public>protected>default>private
- 1,外部类:public/default
- 2,成员内部类:public/protected/default/private
- 3,局部内部类;什么都不能写
匿名内部类
/*
* 如果接口的实现类(或者是父类的子类)只需要使用唯一的一次
* 那么这种情况下就可以省略掉该类的定义 而改为使用【匿名内部类】
*
* 匿名内部类的定义格式:
* 接口名称 对象名=new 接口名称(){
* 覆盖重写所有抽象方法
* };
*
* 对格式进行解析 new接口名称(){...} 进行解析
* 1,new代表创建对象的动作
* 2,接口名称就是匿名内部类需要实现那个接口
* 3,{...这才是匿名内部类的内容}
*
* 另外还需要注意几点问题:
* 1,匿名内部类 在创建对象的时候 只能使用唯一一次
* 如果希望多次创建对象 而且类的内容一样的话 那么就必须使用单独定义实现类
* 2,匿名对象 在调用方法的时候 只能调用一次
* 如果希望 同一个对象 调用多次方法 那么必须给对象取个名字
* 3,匿名内部类是省略了实现类子类的 但是匿名对象是省略了对象名称
* 匿名内部类 和匿名对象不是一回事*/
public class DemoMain {
public static void main(String[] args) {
// MyInterface obj=new MyInterfaceImpl();
// obj.method();
MyInterface objA=new MyInterface() {
@Override
public void method1() {
System.out.println("匿名内部类实现了方法1");
}
@Override
public void method2() {
System.out.println("匿名内部类实现了方法2");
}
};
objA.method1();
objA.method2();
System.out.println("=====================");
new MyInterface() {
@Override
public void method1() {
System.out.println("匿名内部类实现了方法1");
}
@Override
public void method2() {
System.out.println("匿名内部类实现了方法2");
}
}.method1();
//匿名对象无法调用第二次方法 所以需要再创建一个匿名内部类匿名对象
}
}
public interface MyInterface {
void method1();
void method2();
}
public class MyInterfaceImpl implements MyInterface {
@Override
public void method1() {
System.out.println("实现类覆盖重写实现了方法");
}
@Override
public void method2() {
System.out.println("实现类覆盖重写实现了方法");
}
}