内部类
内部类:就是在一个类中定义另外一个类!(以后看源码:比如:集合中的迭代器)
-
在A类中定义一个B类,那么将B类就称为A类的内部类,A类就是B类的外部类!
-
内部类是可以访问外部类的成员,包括私有!
内部类的分类:
-
成员内部类:
在外部类的成员位置定义的类
-
局部内部类:
在局部位置(外部类的成员方法中)定义的一个类
访问方式:
在测试类中,要访问内部类的成员:
-
外部类名.内部类名 对象名 = 外部类对象().内部类对象();
//定义一个外部类
class Outer{
//成员变量
private int num = 100 ;
//定义一个内部类(成员内部类 :一般说成员内部类都是默认非静态!)
class Inner{
//定义一个show()方法
public void show() {
System.out.println(num);//直接可以访问外部类包括私有!
}
}
//外部类的成员方法:
public void method() {
//show();
//外部类的成员要访问内部类成员,必须通过对象来访问
//创建内部类对象
Inner inner = new Inner();
inner.show();
//局部内部类
class Inner2{
}
}
}
public class InnerClassDemo1 {
public static void main(String[] args) {
//需要在这里来访问成员内部类的成员!
//外部类名.内部类名 对象名 = 外部类对象().内部类对象();
Outer3.Inner3 oi = new Outer3().new Inner3() ;
oi.show();
}
}
成员内部类它的一些修饰符
-
private :能够保证内部类的数据的安全性
-
static : 静态的成员内部类
-
被static修饰的成员内部类:
它里面的成员方法(可以静态/非静态)只能访问外部类中静态的成员!(必须使用static修饰)
-
在测试类中,访问静态成员内部类的成员方法的时候,访问方式如下:
外部类名.内部类名 对象名 = new 外部类名.内部类名() ;
//定义外部类
class Outer4{
public int num = 100;
public static int num2 = 50 ;
//加入static修饰的成员内部类
static class Inner4{
//定义一个成员方法
public void show() {
//System.out.println(num); //外部类的成员变量没有加入static修饰
System.out.println(num2);
}
public static void show2() {
//System.out.println(num); //外部类的成员变量没有加入static修饰
System.out.println(num2);
}
}
}
//测试类中
public class InnerClassDemo4 {
public static void main(String[] args) {
//需要访问静态的成员内部类中的成员方法!
//外部类名.内部类名 对象名 = 外部类对象().内部类对象();
//Outer4.Inner4 oi = new Outer4().new Inner4(); 这种方式行不通!
//静态的成员内部类中成员的访问方式:
//外部类名.内部类名 对象名 = new 外部类名.内部类名() ;
Outer4.Inner4 oi = new Outer4.Inner4() ;//类上Inner4此时就相当于外部类的静态成员方法.
oi.show();
局部内部类:
在局部位置定义的类,
特点:
1)可以直接访问外部类的成员,包括私有!
2)在外部类的成员方法中,可以通过创建局部内部类对象来访问局部内部类的成员
-
JDK7以前(包含JDK7),局部内部类访问局部变量,局部变量必须加入final修饰,否则报错!
-
JDK7以后,局部变量会自动加上final,开发者不需要定义final关键字,为什么要加final?
原因:
局部变量的生命周期,随着方法调用而存在,随着方法调用完毕而消失,
而当前这个局部变量被局部内部类在进行访问(局部内部类对象进行访问),在堆内存中对象不会被立即回收,它还在
继续使用这个局部变量,需要将这个变量定义为常量,常驻内存---->以便局部内部类对象对该局部变量的访问!
匿名内部类
**匿名内部类:**它是内部类一种简化方式!
-
格式:
new 类(可以是具体类,也可抽象类)名/接口名(){
重写方法;
};
匿名内部类的好处:
省去了繁杂的代码,不需要定义类里面的子类或者接口的子实现类,写法比较简单!
匿名内部类的本质就是:继承该类或者是实现了该接口的子类对象!
//定义一个接口
interface Inner{
//抽象方法
public abstract void show() ;
public abstract void show2() ;
}
//定义一个类
class Outer6{
Inner i = new Inner() {
@Override
public void show() {
System.out.println("show Inner");
}
@Override
public void show2() {
System.out.println("show2 Inner");
}
}; //相当于接口的子实现类
i.show();
i.show2();
}
}
public class InnerClassDemo6 {
public static void main(String[] args) {
//创建外部类对象
Outer6 outer = new Outer6() ;
outer.method();
}
}
匿名参数类型传递
package com.qianfeng_innerclass_04;
/*
* 方法形式参数是一个类: 传递该类具体对象
* 抽象类:需要传递该抽象类的子类对象
* 接口:需要传递该接口的子实现类对象
*
*
* 匿名内部类在开发中的使用:
* 方法形式参数或者返回值中常见就是形参是抽象类/接口
* 返回值是抽象类/接口
* */
//定义具体类
class Student{
public void study() {
System.out.println("学习JavaEE...");
}
}
//定义一个StudentDemo类
class StudentDemo{
public void method(Student s) {//形参传递是具体类
s.study();
}
}
//测试类
public class InnerClassTest {
public static void main(String[] args) {
//创建StudentDemo类的方法,访问method方法
StudentDemo sd = new StudentDemo() ;
Student s = new Student() ; //具体类可以实例化(最简单,最直接! )
sd.method(s);
System.out.println("------------");
//匿名内部类
/*
* new 类名(具体类名/抽象类类名)/ 接口名(){
* 重写方法;
* };
* */
StudentDemo sd2 = new StudentDemo() ;
sd.method(new Student() { //具体类!
//重写study方法
public void study() {
System.out.println("一鼓作气,再而衰,三而竭!");
}
});
}
}
匿名参数类型传递2
package com.qianfeng_innerclass_04;
/*
* 方法形式参数如果
* 接口: 传递需要改接口子实现类对象
*
* */
//定义一个接口
interface Love{
void love() ;
}
//定义一个类
class PersonDemo{
public void function(Love love) {
love.love();
}
}
//定义一个子实现类
class Worker implements Love{
@Override
public void love() {
System.out.println("爱生活,爱Java...");
}
}
//测试类
public class InnerClassTest2 {
public static void main(String[] args) {
//需要调用PersonDemo类中的function方法
PersonDemo pd = new PersonDemo() ;
//Love love = new Love() ;//不能实例化
//接口多态:
Love love = new Worker();
pd.function(love);
System.out.println("---------------------");
//接口匿名内部类的使用
PersonDemo pd2 = new PersonDemo() ;
/*
* new 接口名(){
* 重写抽象方法;
* };
*
* */
pd2.function(new Love() { //接口匿名内部类对象(本质就是子实现类!)
@Override
public void love() {
System.out.println("爱生活...");
}
});
}
}