一、成员内部类
1、成员内部类:定义在A类里面的B类就是内部类,B类在A类内部地位与其他成员相同,可以相互调用
2、成员内部类的作用:
//这里可以让X同时拥有A B两个类的功能,相当于通过内部类间接实现了多继承
class A{
}
class B{
}
class X extends A{ //使X拥有A和B的功能,间接实现了多继承
class Y extends B{
}
}
3、创建成员内部类的两种方法:
public class Demo2 {
public static void main(String[] args) {
//方法一:先获取内部类的对象再调用方法
//1.先创建外部类对象
Outer outer = new Outer();
//2.创建内部类的对象 构成:外部类对象.new 内部类构造方法
day12.Outer.Inner inner = outer.new Inner();//使用类的全称是包名.类名
Inner inner1 = outer.new Inner();//通过导包创建(不推荐使用)
inner.play();
//方法二:借助于外部类的方法,实现内部类对象的创建并调用方法
outer.show();
}
}
class Outer{
int age;
class Inner{//内部类
int height = 170;
public void play(){
System.out.println("Inner-play");
}
}
public void show() {
System.out.println("Outer-show"+age);
//创建内部类对象并调用方法
Inner inner = new Inner();
inner.play();
}
}
二、局部内部类
1、局部内部类:定义在外部类方法中的类
局部内部类的作用范围:从定义它开始到他所在的方法结束
2、局部内部类的功能:
- 通过局部内部类实现方法功能的私有化
- 对方法内部的代码进行整理,增强了代码的可读性和可操作性
class Temp{
//实现的功能:只允许play调用gongneng1()和gongneng2(),run()不能调用
//方法之间不能嵌套,但方法中可以放内部类
public void play() {
class Inner{
public void gongneng1() {
}
public void gongneng2() {
}
}
Inner inner = new Inner();
inner.gongneng1();
inner.gongneng2();
}
public void run() {
//两个小方法对run不可见
//gongneng1();
//gongneng2();
}
}
3、
了解:
局部内部类所在的方法中局部变量的使用.
- 局部变量的作用域:定义变量开始到函数结束
- final:被final修饰的变量会被放在常量区,而常量区的值存在的时间要大于局部变量所在的方法,相当于从原来的基础上扩大了作用域
原理:
- 当方法中同时存在局部内部类与局部变量时,局部变量的使用范围就会从原来的基础上进行扩大.
原因:
-
在当前的情况下,程序会默 认让final去修饰weight.所以当局部变量所在的方法结束的时候,变量没有被释放,保存的值还在.
-
关于变量前面的final:
前提:变量必须与局部内部类同时存在.
在jdk1.7之前要想保住局部变量的值,要手动添加final
在jdk1.7之后,java的内部机制已经在变量的前面默认添加了final
public class Demo3 {
public static void main(String[] args) {
//创建Outer1对象
Outer1 outer1 = new Outer1();
outer1.show();
}
}
class Outer1{
int age;
public void show() {
System.out.println("Outer-show"+age);
/* final */int weight = 20; //前面默认又final,延长使用寿命,防止其随show方法结束而消失
class Inner{ //局部内部类
int height = 170;
public void play(){
System.out.println("Inner-play");
}
}
//创建内部类对象并调用方法
Inner inner = new Inner();
inner.play();
}
}
三、静态内部类
public class Demo4 {
public static void main(String[] args) {
//静态的对象
//注意:要保证内部类是静态的
//构成:new 外部类.内部类的构造方法
Outer3.Inner inner = new Outer3.Inner();
//调用非静态方法
inner.play();
//调用静态方法
Outer3.Inner.show();
}
}
class Outer3{
static class Inner{ //静态内部类
int height = 170;
//非静态方法
public void play(){
System.out.println("Inner-play");
}
//静态方法
public static void show() {
System.out.println("Inner-show");
}
}
}
注意点:
- 1.静态内部类中可以没有静态的成员
- 2.有静态成员的一定是静态内部类
(和抽象类一个脾气。。。)
四、匿名内部类
1、匿名内部类(对象):定义在一个类方法中的匿名子类对象,属于局部内部类
- 匿名对象和匿名子类对象
- 匿名内部类对象
public class Demo5 {
public static void test(Animal animal) {
animal.eat();
}
public static void main(String[] args) {
Animal animal = new Animal();
animal.eat();
//匿名对象:没有名字的对象,只能在创建的时候使用一次,之后会变成垃圾等待回收
//场景:可以作为参数传递 作用:节省代码,节省内存
new Animal().eat();
test(new Animal());
//创建匿名子类对象
//第一种创建方式
//使用已有的子类创建匿名子类对象并调用方法
//场景:现有的子类可以使用多次---相同的功能需要调用多次的时候
new Dog().eat();
//第二种创建方式
//直接创建没有名字的Animal的匿名子类对象
//构成:new + 父类/父接口的名字 + () + {匿名子类的执行体};
//场景:只能使用一次,使用完会被回收---每次都使用不同的功能
new Animal() {
@Override
public void eat() {
System.out.println("匿名子类---eat");
}
public void show() { //写第二个方法没有意义,因为通过匿名子类对象一次只能调用一个方法,调用之后即被回收,第二个方法写了也调用不了
System.out.println("show");
}
}.eat(); //直接创建匿名子类对象并调用匿名子类中的方法
//研究匿名内部类
Out out = new Out();
out.show();
}
}
//研究匿名对象和匿名子类对象
class Animal{
public void eat() {
System.out.println("Animal-eat");
}
}
class Dog extends Animal{
public void eat() {
System.out.println("Dog-eat");
}
}
//研究匿名内部类
class Out{
public void show() {
new Animal() {
@Override
public void eat() {
System.out.println("匿名子类---eat");
}
public void show() { //写第二个方法没有意义,因为通过匿名子类对象一次只能调用一个方法,调用之后即被回收,第二个方法写了也调用不了
System.out.println("show");
}
}.show();
}
//使用普通的匿名对象充当参数
public void canshu1() {
System.out.println(new Animal());
}
//匿名内部类充当参数
public void canshu2() {
System.out.println(new Animal() {
});
}
//使用普通的匿名对象充当返回值
public Animal fanhuizhi1() {
return new Animal();
}
//匿名内部类充当返回值
public Animal fanhuizhi2() {
return new Animal() {
@Override
public String toString() {
return "哈哈";
}
};
}
}
//自己测试创建接口的匿名内部类---作为参数,返回值