1、内部类概述和访问特点
内部类概述:
把类定义在其他类的内部,这个类就被称为内部类。
举例:在类A中定义了一个类B,类B就是内部类。
内部类访问特点
a:内部类可以直接访问外部类的成员,包括私有。
b:外部类要访问内部类的成员,必须创建对象。
2、内部类分类
根据内部类定义的位置不同可以分为:成员内部类和局部内部类 成员内部类:将内部类定义到外部类的成员位置 局部内部类:将内部类定义到外部类的局部位置(方法内)
class Wai{
//成员内部类
class cNei {
}
public void show(){
//局部内部类
class jNei{
}
}
}
3、成员内部类的直接使用
成员内部类
如何在测试类中直接访问内部类的成员。
格式: 外部类名.内部类名 对象名 = 外部类对象.内部类对象;
public class Wai {
int num=20;
private double a=100;
class Nei{
int b=40;
public void neiShow(){
System.out.println("nei show"+b);
System.out.println(num);
System.out.println(a);
waiShow();
waiShow2();
}
public void neiTest(){
System.out.println("abc");
}
}
public void waiShow(){
System.out.println("外部类的show");
}
private void waiShow2() {
System.out.println("外部类的show");
}
public void hehe(){
//neiTest()
//外部类要访问内部类的成员,要创建内部类的对象。
Nei nei = new Nei();
nei.neiTest();
}
}
public class MyTest {
public static void main(String[] args) {
//怎么调用成员内部类的属性和方法。
//创建成员内部类的对象
// 如何在测试类中直接访问内部类的成员。
// 格式:
// 外部类名.内部类名 对象名 = 外部类对象.内部类对象;
Wai.Nei nei=new Wai().new Nei();
nei.neiShow();
System.out.println(nei.b);
new Wai().hehe();
//内部类的特点:可以直接访问外部类的成员,包括私有成员。
}
}
4、成员内部类的常见修饰符及应用
成员内部类的修饰符:
private 为了保证数据的安全性
static 为了方便访问数据
注意事项: a:静态内部类访问的外部类数据必须用静态修饰。
b: 成员方法可以是静态的也可以是非静态的
成员内部类被静态修饰后的访问方式是:
格式: 外部类名.内部类名 对象名 = new 外部类名.内部类名();
static修饰内部类:
public class MyTest {
public static void main(String[] args) {
// 静态的成员内部类,创建对象的语法是这样的
Outer.Inner inner=new Outer.Inner();
inner.show();
inner.hehe();
}
}
class Outer{
int c=1;
static int num=200;
//静态可以修饰内部类。
//静态内部类,只能访问外部类的静态成员,非静态成员无法访问。
static class Inner{
int a=20;
static int b=200;
public void show(){
System.out.println(num);
haha();
}
public static void hehe(){
System.out.println(num);
}
}
public static void haha(){
System.out.println("haha");
}
}
private修饰内部类:
public class MyTest {
public static void main(String[] args) {
//内部类一旦被私有,外键就无法创建其对象了。
// Wai.Nei nei = new Wai().new Nei();
Wai wai = new Wai();
wai.haha();
}
}
class Wai {
//内部类可以私有
private class Nei {
public void neiShow(){
System.out.println("nei show");
}
}
public void haha(){
Nei nei = new Nei();
nei.neiShow();
}
}
成员内部类的面试题
A:面试题
要求:使用已知的变量,在控制台输出30,20,10。
class Outer {
public int num = 10;
class Inner {
public int num = 20;
public void show() {
int num = 30;
System.out.println(num);
System.out.println(num);
System.out.println(num);
}
}
}
class InnerClassTest {
public static void main(String[] args) {
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}
class Outer {
public int num= 10;
public int b=20;
class Inner {
public int num = 20;
public void show() {
//要求:使用已知的变量,在控制台输出30,20,10。
int num = 30;
System.out.println(num); //30
System.out.println(this.num); //20
//System.out.println(new Outer().num); //10
//在内部类的方法中,访问外部类的成员可以此语法。
System.out.println(Outer.this.num); //10
System.out.println(b);
}
}
}
class InnerClassTest {
public static void main(String[] args) {
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}
5、局部内部类访问局部变量
可以直接访问外部类的成员
可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能
局部内部类,在外界没有直接创建其对象的语法。
public class MyTest {
public static void main(String[] args) {
//内部类可以直接访问外部类的成员,包括私有成员。
//局部内部类,在外界没有直接创建其对象的语法。
Wai wai = new Wai();
wai.show();
}
}
class Wai{
int a=10;
private int num=100;
public void show(){
//局部内部类型
class Nei{
public void neiShow(){
System.out.println(a);
System.out.println(num);
}
}
//创建局部内部类的对象
Nei nei = new Nei();
nei.neiShow();
}
}
局部内部类访问局部变量必须用final修饰
为什么呢?
因为局部变量会随着方法的调用完毕而消失,这个时候,局部对象并没有立马从堆内存中消失,还要使用那个变量。为了让数据还能继续被使用,就用fianl修饰,这样,在堆内存里面存储的其实是一个常量值。JDK1.8之后,final会默认加上,你不用手动去加,但是你要知道
6、匿名内部类的格式和理解
匿名内部类: 就是局部内部类的简化写法。
前提: 存在一个类或者接口;这里的类可以是具体类也可以是抽象类
本质:是一个继承了该类或者实现了该接口的子类匿名对象
格式:
new 类名或者接口名(){
重写方法;
} ;
匿名内部类代替抽象类子类匿名对象:
public class MyTest {
public static void main(String[] args) {
new AA() {
@Override
public void aa() {
System.out.println("重写aa方法");
}
@Override
public void bb() {
System.out.println("重写bb方法");
}
};
new AA() {
@Override
public void aa() {
System.out.println("我重写了aa方法2");
}
@Override
public void bb() {
System.out.println("我重写了bb方法2");
}
}.aa();
//多态
AA myaa = new AA() {
@Override
public void aa() {
System.out.println("我重写了aa方法2");
}
@Override
public void bb() {
System.out.println("我重写了bb方法2");
}
};
myaa.aa();
myaa.bb();
}
}
abstract class AA {
public abstract void aa();
public abstract void bb();
}
匿名内部类代替接口子类匿名对象:
public class MyTest2 {
public static void main(String[] args) {
// CC cc = new CC();
// cc.test();
//我只想要一个接口的子类对象
MyInterface myInterface = new MyInterface() {
@Override
public void test() {
System.out.println("cccccccccccccccccccdeedfefefef");
}
@Override
public void aa() {
System.out.println("ccccccccccccccccccccccccccererer");
}
};
myInterface.test();
myInterface.aa();
}
}
interface MyInterface {
void test();
void aa();
}
/*
class CC implements MyInterface{
@Override
public void test() {
System.out.println("abc");
}
}*/
7、匿名内部类作传参或返回值
传参
public class MyTest {
public static void main(String[] args) {
//匿名内部类,经常作为参数或返回值比较方便
//如果你以后看到一个方法的形参要一个抽象类 类型,你就传递一个该抽象类的子类对象。
// CC cc = new CC();
// set(cc);
BB bb = new BB() {
@Override
public void hehe() {
System.out.println("ccccccccccccccccccccccc");
}
};
set(bb);
set(new BB() {
@Override
public void hehe() {
System.out.println("aaaaaaaaaaaaaaaaaaaaaaaaaaa");
}
});
MyInterface my= new MyInterface() {
@Override
public void show() {
System.out.println("dddddddddddddddddddddddddd");
}
};
set(my);
set(new MyInterface() {
@Override
public void show() {
System.out.println("cccccccccccccccccccc");
}
});
}
public static void set(BB bb) {
bb.hehe();
}
public static void set(MyInterface myInterface) {
myInterface.show();
}
}
abstract class BB {
public abstract void hehe();
}
interface MyInterface{
void show();
}
返回值
public class MyTest2 {
public static void main(String[] args) {
EE ee = getEE();
ee.hehe();
EE ee1 = getEE();
ee1.hehe();
}
//当你以后看到一个方法的返回值类型要一个抽象类类型,你就返回该抽象类的子类对象
public static EE getEE(){
// TT tt = new TT();
EE ee = new EE() {
@Override
public void hehe() {
System.out.println("rrrrr");
}
};
return ee;
}
}
abstract class EE{
public abstract void hehe();
}
class TT extends EE{
@Override
public void hehe() {
System.out.println("bbbb");
}
}
8、匿名内部类中this关键字
interface Inter {
public static final int a = 23;
}
public class MyTest2 {
public static void main(String[] args) {
new Inter() {
public void show() {
//this 代表匿名内部类
System.out.println(this.a);
System.out.println(Inter.a);
}
}.show();
}
}
9、类中定义接口
public class MyTest {
public static void main(String[] args) {
/*
Wai.MyInterface myInterface = new Wai.MyInterface() {
@Override
public void show() {
System.out.println("重写了接口的方法");
}
};
myInterface.show();
*/
Wai wai = new Wai();
wai.hehe();
}
}
class Wai {
//内部接口
private interface MyInterface {
void show();
}
public void hehe() {
MyInterface myInterface = new MyInterface() {
@Override
public void show() {
System.out.println("abc");
}
};
myInterface.show();
}
}
A:问题引出
首先回顾我们曾经讲过的方法的形式参数是引用类型的情况,
我们知道这里需要一个子类对象。而匿名内部类就是一个子类匿名对象,
所以,可以使用匿名内部类改进以前的做法。
B:代码如下
//这里写抽象类,接口都行
abstract class Person {
public abstract void show();
}
class PersonDemo {
public void method(Person p) {
p.show();
}
}
class PersonTest {
public static void main(String[] args) {
//如何调用PersonDemo中的method方法呢?
}
}abstract class Person { public abstract void show(); } class PersonDemo { public void method(Person p) { p.show(); } } class PersonTest { public static void main(String[] args) { //如何调用PersonDemo中的method方法呢? new PersonDemo().method(new Person() { @Override public void show() { System.out.println("abc"); } }); } }