内部类
一,内部类的概述
内部类:在一个类A中存在另一个类B,那么这个类B就是一个内部类。
二,内部类访问特点
(1)内部类可以直接访问外部类的成员,包括私有
(2)外部类必须通过创建该内部类的对象访问该内部类的成员。
package org.westos_内部类;
/**
* 在一个类中定义另一个类,那么把这种情况:内部类:
* 举例:
* 在类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)局部内部类:定义在外部类的局部位置
(2)成员内部类:在外部类的成员位置
package org.westos_内部类;
/**
* 内部类的分类:
* 成员内部类:在外部类的成员位置
* 局部内部类:在外部了的局部位置定义的这个类
*
* */
//外部类
class Outer2{
//外部类的成员变量
public int num = 100 ;
//成员内部类
/*class Inner2{
}*/
//外部类的成员方法
public void method(){
//局部位置
class Inner2{
}
}
}
//测试类
public class InnerDemo2 {
public static void main(String[] args) {
}
}
三, 成员内部类
(1)在测试类中需要访问成员内部类中的成员的方法:
外部类名.内部类名 对象名 = 外部类对象.内部类对象
(2)成员内部类的修饰符:
private :为了保证数的安全性
static修饰:为了方便调用
如果成员内部类被static修饰,那么要访问外部类的成员变量,这个变量必须被static修饰
*
* 静态的成员内部类访问该类中的成员方法:
格式:
外部类名.内部类名 对象名 = new 外部类名.内部类名() ;
*或者外部类名.内部类名.变量或方法名。
对于静态的成员内部类来说,无论静态成员内部类中的成员方法是静态还是非静态的,要访问外部类的成员变量,该变量必须被static修饰
package org.westos_内部类;
/**
* 成员内部类的修饰符:
* private :为了保证数的安全性
* static修饰:为了方便调用
* 如果成员内部类被static修饰,那么要访问外部类的成员变量,这个变量必须被static修饰
*
* 静态的成员内部类访问该类中的成员方法:
格式:外部类名.内部类名 对象名 = new 外部类名.内部类名() ;
*
//外部类
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() ;
}
}
四,局部内部类
当前局部变量报错,必须用final修饰;为什么用final修饰?
package org.westos_内部类;
/**
* 局部内部类:
* 定义在外部类的局部位置
*
* 结论:
* 无论是局部内部类还是成员内部类(非静态的)都可以直接访问外部类的成员,包括私有
*
* 面试题:
* 局部内部类访问局部变量会出现问题?
* 当前局部变量报错,必须用final修饰;为什么用final修饰?
* 是由于局部变量是随着方法调用而生成的,随着方法的调用完毕消失,而现在局部位置有一个局部内部类它要在自己的成员方法位置访问当前的局部变量
* 必须把变量变成一个常量,(需要用final:自定义常量),这样的一个变量的值永远是固定的!
*
* */
//外部类
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();
}
}
package org.westos_内部类;
/**
*
* 看程序
* 面试题:
要求请填空分别输出30,20,10。
外部类和内部类没有继承关系!
* */
class Outer7 {
public int num = 10;
class Inner7 {
public int num = 20;
public void show() {
int num = 30;
System.out.println(num);
System.out.println(this.num);
System.out.println(new Outer7().num);//要访问外部类的成员变量:匿名对象 :new 外部类名().成员变量
//外部类的this限定
System.out.println(Outer7.this.num);
}
}
}
public class InnerClassTest {
public static void main(String[] args) {
Outer7.Inner7 oi = new Outer7().new Inner7();
oi.show();
}
}
五,匿名内部类
匿名内部类:内部类的简化格式
package org.westos_内部类;
/**
* 匿名内部类
* 是内部类的简化版格式
* 前提条件:
* 必须存在一个接口或者是一个类(可以是具体类,也可以是一个抽象类)
*
* 书写的格式:
* 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() ;
}
}
package org.westos_内部类;
/**
* 匿名内部类在开发中的使用
* */
interface Inter3{
public abstract void study() ;
}
class StudentDemo{
public void method(Inter3 i){//形式参数是一个接口
i.study() ;
}
}
//方式1:
class Armay implements Inter3{
public void study(){
System.out.println("好好学习,天天向上...");
}
}
//方式2:
//测试类
public class OuterTest {
public static void main(String[] args) {
//需求:调用StudentDemo中的method()方法
StudentDemo sd = new StudentDemo() ;
Inter3 i = new Armay() ;
i.study() ;
System.out.println("---------------------");
//方式2:匿名内部类
StudentDemo sd2 = new StudentDemo() ;
sd2.method(new Inter3(){
@Override
public void study() {
System.out.println("好好学习,天天向上...");
}
}) ;
}
}
package org.westos_内部类;
/**
* 匿名内部类面试题:
按照要求,补齐代码
interface Inter { void show(); }
class Outer { //补齐代码 }
class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
}
}
要求在控制台输出”HelloWorld”
* */
//接口
interface Inter2{
// void show() ;
public abstract void show() ;
}
class Outer8{
//补齐代码
public static Inter2 method(){ //返回值是一个接口
return new Inter2(){
@Override
public void show() {
System.out.println("helloworld");
}
} ;
}
}
//测试类
public class InnerClassTest2 {
public static void main(String[] args) {
Outer8.method().show();
//当前method()能直接被类名调用---->method()方法是一个静态方法 static
//Outer8.method().show()---->Outer8.method()返回的是一个对象,拿对象调用show()方法
//由于接口只有一个show()方法,最终要去重写show()方法
}
}