一.
定义:
在一个类中定义另一个类,那么把这种情况:内部类:
举例:
在类A中定义一个类B,那么类B就是类A的内部类,同理,类A就是类B的外部类
内部类是直接可以访问外部类的成员,包括私有
外部类想要访问内部类的成员,必须通过创建内部类的对象访问该内部类的成员
//外部类
class Outer{
//外部类的成员变量
// public int num = 100 ;
private int num = 20 ;
//内部类
class Inner{
//内部类的成员方法
public void show(){
System.out.println(num);
}
}
//外部类的成员方法
public void method(){
// show() ;
//创建内部类对象
Inner i = new Inner() ;
i.show() ;
}
}
//测试类
public class InnerDemo {
public static void main(String[] args) {
}
}
二.
内部类的分类:
1.成员内部类
在测试类中需要访问成员内部类中的成员的方法:
外部类名.内部类名 对象名 = 外部类对象.内部类对象;
//外部类
class Outer3{
//定义外部类的变量
public int num = 10 ;
//成员内部类
class Inner3{
//内部类的成员方法(非静态的成员方法)
public void show(){
System.out.println(num);
}
}
/*public void method(){
Inner3 i = new Inner3() ;
i.show() ;
}*/
}
//测试类
public class InnerDemo3 {
public static void main(String[] args) {
/**
* 需求:现在需要访问Inner3成员内部类中的show()方法
* */
// Inner3 i = new Inner3() ; //Inner3是一个成员内部类
// 外部类名.内部类名 对象名 = 外部类对象.内部类对象;
Outer3.Inner3 oi = new Outer3().new Inner3() ;
//使用对象名调用show()方法
oi.show() ;
}
}
成员内部类的修饰符:
private :为了保证数的安全性
static修饰:为了方便调用
如果成员内部类被static修饰,那么要访问外部类的成员变量,这个变量必须被static修饰
静态的成员内部类访问该类中的成员方法:
格式:外部类名.内部类名 对象名 = new 外部类名.内部类名() ;
案例:
class Body{
* //心脏
* //成员内部类
* private class Inner{
* public void operator(){
* System.out.println("心脏搭桥手术");
* }
* }
*
* public void behivour(){
* if("你是外科医生"){
* Inner i = new Inner() ;
* i.operator();
* }
* }
* }
*
* 刚才创建对象:外部类名.内部类 对象名 =外部类对象.内部类对象;
* Body.Inner bo = new Body().new Inner() ;//错误的
* bo.operator() ;
*
* 可以直接创建外部类对象Body b = new Body();
* b.behivour();
*
* */
//外部类
class Outer4{
//外部类的两个成员变量
public static int num = 10 ;
public static int num2 = 20 ;
/**
* 结论:
* 对于静态的成员内部类来说,无论静态成员内部类中的成员方法是静态还是非静态的,要访问外部类的成员变量,该变量必须被static修饰
* */
//定义一个静态的成员内部类
public static class Inner4{
//非静态的内部类的成员方法
public void show(){
System.out.println(num);
System.out.println(num2);
}
//静态的内部类的成员方法
public static void show2(){
System.out.println(num);
System.out.println(num2);
}
}
}
//测试类
public class InnerDemo4 {
public static void main(String[] args) {
//需求:要访问静态成员内部类Inner4里面的show(),show2()方法
//外部类名.内部类 对象名 =外部类对象.内部类对象;
// Outer4.Inner4 oi = new Outer4().new Inner4() ;
// oi.show() ;
//静态的成员内部类访问该类中的成员方法:
//格式:外部类名.内部类名 对象名 = new 外部类名.内部类名() ;
Outer4.Inner4 oi = new Outer4.Inner4() ;
oi.show() ;
oi.show2() ;//静态方法
System.out.println("--------------");
//show2()还有另外一种访问方式:
Outer4.Inner4.show2() ;
}
}
2.局部内部类:
定义在外部类的局部位置
结论:
无论是局部内部类还是成员内部类(非静态的)都可以直接访问外部类的成员,包括私有
//外部类
class Outer5{
//外部类的成员变量
// public int num = 100 ;
private int num = 100 ;
//外部类的成员方法
public void method(){
//局部变量
final int num2 = 200 ; //自定义常量(细节问题)
//局部位置
class Inner5{
//局部内部类的成员方法
public void show(){
System.out.println(num);
//局部内部类中访问局部变量
System.out.println(num2); //jdk1.7才会有这个错误! jdk1.8---->封装好了,所以不会出现错误!
}
}
Inner5 i = new Inner5() ;
i.show() ;
}
}
//测试类
public class InnerDemo5 {
public static void main(String[] args) {
//对于局部内部类访问具该类的成员方法:创建外部类对象 使用外部类对象调用外部类的成员方法
Outer5 o = new Outer5() ;
o.method() ;
}
}
3.匿名内部类
是内部类的简化版格式
前提条件:
必须存在一个接口或者是一个类(可以是具体类,也可以是一个抽象类)
书写的格式:
new 接口名或者类名(){
方法重写;
}
匿名内部类的实质:
继承了该类(抽象类)或者是实现了该接口的子类对象!
//定义一个接口
interface Inter{
//抽象功能
public abstract void show() ;
public abstract void show2() ;
}
//外部类
class Outer6{
//成员方法
public void method(){
//当接口中有一个方法的时候
// new Inter(){
//
// @Override
// public void show() {
// System.out.println("show");
// }
//
// }.show() ;
//当接口中有两个方法的时候
/*new Inter(){
@Override
public void show() {
System.out.println("show");
}
@Override
public void show2() {
System.out.println("show2");
}
}.show() ;
new Inter(){
@Override
public void show() {
System.out.println("show");
}
@Override
public void show2() {
System.out.println("show2");
}
}.show2();*/
//使用接口名 对象名 = 匿名内部类的格式: new 接口名(){
//方法重写();
//}
// Inter i2 = new Inter() ;
Inter i = new Inter(){
@Override
public void show() {
System.out.println("show");
}
@Override
public void show2() {
System.out.println("show2");
}
};
//使用对象名调用
i.show();
i.show2() ;
}
}
//测试类
public class InnerDemo6 {
public static void main(String[] args) {
Outer6 o = new Outer6() ;
o.method() ;
}
}
三.补充
局部内部类访问局部变量会出现问题?
当前局部变量报错,必须用final修饰;为什么用final修饰?
是由于局部变量是随着方法调用而生成的,随着方法的调用完毕消失,而现在局部位置有一个局部内部类它要在自己的成员方法位置访问当前的局部变量
必须把变量变成一个常量,(需要用final:自定义常量),这样的一个变量的值永远是固定的!