如果一个事物的内部包含另一个事物,那么这就是一个类的内部包含另一个类
例如身体和心脏的关系。又如汽车和发动机的关系
分类:
1 成员内部类
定义: 成员内部类的定义格式:
修饰符 class 外部类名称{
修饰符 class 内部类名称 {
//....
}
//........
}
使用:两种方式
A 间接方法:在外部类方法中 使用内部类;然后main只是调用外部类的方法
B 直接方式:
参考: **类名称 对象名=new 类名称();
公式:【外部类名称.内部类名称 对象名=new 外部类名称().new 内部类名称();】
成员变量如果重名了 可以使用
外部类名称.this.外部类成员变量
package neibulei.Demo4; //独立文件
public class Ceshi {
public void methodCeshi(){
int num=100;
// num=200;
class InterCeshi{
public void methodInter(){
System.out.println(num);
}
}
}
}
=======================
package neibulei.Demo1; //独立文件
public class Test {
public static void main(String[] args) {
Body t=new Body();
Body.Herat a1=t.getHerat();
//通过外部类的对象 调用外部类的方法 里面间接在使用内部类Heart
a1.beat();
t.getHerat().beat();
Body.Herat a2=new Body().new Herat();
//直接通过
// 【外部类名称.内部类名称 对象名=new 外部类名称().new 内部类名称();】
a2.beat();
}
}
2 局部内部类(包含匿名内部类)
局部内部类
如何一个类是定义在一个方法内部的,那么这就是一个局部内部类。
“局部”:只有当前所属的方法才能使用它,出了这个方法外面就不能用了
定义格式:
修饰符 class外部类名称{
修饰符 返回值类型 外部类方法名称(参数列表){
class 局部内部名称{
//....
}
}
}
===========
package neibulei.Demo3; //独立文件
public class Outer {
public void methodOuter(){
int num=10;
class Inter{
public void methodInter(){
System.out.println(num);
}
}
Inter a=new Inter();
a.methodInter();
}
}
===========
package neibulei.Demo3; //独立文件
public class Test {
public static void main(String[] args) {
Outer t=new Outer();
t.methodOuter();
}
}
小结一下类的权限修饰符:
public>protected>(default)>private
定义一个类的时候:权限修饰符规则:
1 外部类:public /(default)
2 成员内部类:publiic / protected /(default) /private
3 局部内部类:什么都不能写
局部类如果希望访问所在方法的局部变量 那么这个变量必须是【有效final的】
备注:从java8开始,只要局部变量事实不变,那么final关键字可以省略
(从内部类引用的本地变量必须是最终变量或实际上的最终变量)
原因::
1 new 出来的对象在堆内存中。
2 局部变量是跟着方法走的,在栈内存中
3 方法运行结束之后,立刻出栈,局部变量就会立刻消失。
4 但是new出来的对象会在堆当中持续存在 直到垃圾回收消失。
package neibulei.Demo4;`
public class Ceshi {
public void methodCeshi(){
int num=100;
// num=200;
class InterCeshi{
public void methodInter(){
System.out.println(num);
}
}
}
public static void main(String[] args) {
}
}
匿名内部类
如果接口的实现类(或者是父类的子类)只需要使用唯一的一次,那么这种情况下就可以省略掉该类的定义,而改为使用【匿名内部类】
定义格式:
接口名称 对象名=new 接口名称{
//覆盖重写所有的抽象方法
}
对格式 “new 接口名称(){…} 进行解析”:
1 new 代表创建对象的动作
2 接口名称就是匿名内部类需要实现哪个接口
3 {…}这才是匿名内部类的内容
另外还要注意几点问题:
1 匿名内部类,在【创建对象】的时候,只能使用唯一一次。
如果希望多次创建对象,而且类的内容一样的话,那么就必须使用单调定义的实现类
2 匿名对象 在【调用方法】的时候,只能调用唯一
如果希望同一个对象,调用多次方法,那么必须给对象取个名字
3 匿名内部类是省略了【实现类/子类名称】但是匿名对象是省略了【对象名称】
强调:匿名内部类和匿名对象不是一回事!
package neibulei.Demo5;
public class DemoTest { //独立文件
public static void main(String[] args) {
MyInterface t=new MyInterface(){ //t是对象名 这是一个匿名对象名称
@Override
public void method() {
System.out.println("匿名内部类调用了");
}
@Override
public void method2() {
System.out.println("2222");
}
};
t.method();
//使用了匿名内部类 而且省略了对象名称 也是匿名对象
new MyInterface(){
@Override
public void method() {
System.out.println("1111");
}
@Override
public void method2() {
System.out.println("33333");
}
}.method();
//因为匿名对象无法调用第二次 所以需要在创建一个匿名内部类的匿名对象
new MyInterface(){
@Override
public void method() {
System.out.println("1111");
}
@Override
public void method2() {
System.out.println("33333");
}
}.method2();
}
}
=========
package neibulei.Demo5;
public interface MyInterface { //独立文件
public abstract void method();
public abstract void method2();
}