- 1 类的五大成员
- 2 内部类及其四个分类
- 一、内部类
- 二、分类
- 3 局部内部类
- 4 匿名内部类
- 5 基于接口的匿名内部类
- 6 基于类的匿名内部类
- 7 匿名内部类的细节
- 8 匿名内部类作为实参进行传递
- 9 成员内部类
- 10 静态内部类
2 内部类及其四个分类 一、内部类属性、方法、构造器、代码块、内部类
一个类的内部又完整的嵌套了另一个类结构。被嵌套的类称为内部类(inner class),嵌套其他类的类称为外部类(outer class)。是类的第五大成员,内部类最大的特点就是可以直接访问私有属性,并且可以体现类与类之间的包含关系,注意:内部类是学习的难点,同时也是重点,后面看底层源码时,有大量的内部类.
class Outer{//外部类
class Inner{ //内部类
}
}
class Other{//外部其他类
}
二、分类
- ➢定义在外部类的局部位置上(比如方法内)
(1)局部内部类(有类名)
(2)匿名内部类(没有类名,重点!!!) - ➢定义在外部类的成员位置上:
(1)成员内部类(没用static修饰)
(2)静态内部类(使用static修饰)
局部内部类:
(1)定义位置–>定义在外部类中的方法内,即方法体内。
(2)本质–>一个类
(3)地位–>局部变量的地位
(4)作用域–>该内部类所在方法
(1)说明:局部内部类是定义在外部类的局部位置,比如方法中,并且有类名。
(2)可以直接访问外部类的所有成员,包含私有的
(3)不能添加访问修饰符,因为它的地位就是一个局部变量。局部变量是不能使用修饰符的。但是可以使用final 修饰,因为局部变量也可以使用final
(4)作用域:仅仅在定义它的方法或代码块中。
(5)局部内部类----访问—>外部类的成员
【访问方式:直接访问】
(6)外部类----访问---->局部内部类的成员
【访问方式:创建对象,再访问(注意:必须在作用域内) 】
(7)外部其他类—不能访问---->局部内部类(因为局部内部类地位是一个局部变量)
(8)如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员) 去访问。
(1)本质是类
(2)内部类
(3)该类没有名字 [系统默认有分配名字]
(4)同时还是一个对象
(5)说明:匿名内部类是定义在外部类的局部位置,比如方法中,并且没有类名
(6)匿名内部类的基本语法
new 接口 或 类(参数列表){
类体
};
5 基于接口的匿名内部类
1.需求:想使用IA接口,并创建对象
2.传统方式:是写一个类,实现该接口,并创建对象.
3.目前需求是:Tiger 类只是使用一次,后面再不使用
4.可以使用匿名内部类来简化开发
5.tiger的编译类型 ? IA
6.tiger的运行类型 ?就是匿名内部类 AnonymousInnerClass$1
底层会分配类名 AnonymousInnerClass$1
class AnonymousInnerClass$1 implements IA {
@Override
public void cry(){
system.out.println("大声叫唤...");
}
}
7.jdk底层在创建匿名内部类AnonymousInnerClass$1,立即马上
就创建了AnonymousInnerClass$1实例,并且把地址/返回给tiger
8.匿名内部类使用一次,就不能再使用
6 基于类的匿名内部类
1.传统方式:用类创建实例对象. 2.目前需求是:Father类只是使用一次,后面再不使用 3.可以使用匿名内部类来简化开发 5.编译类型 ? Father 6.运行类型 ? 就是匿名内部类 AnonymousInnerClass2$1 底层会分配类名 AnonymousInnerClass2$1 7.匿名内部类使用一次,就不能再使用7 匿名内部类的细节
(1)匿名内部类的语法比较奇特,因为匿名内部类既是一个类的定义,同时它本身也是一个对象。因此从语法上看,它既有定义类的特征,也有创建对象的特征,对前面代码分析可以看出这个特点,因此可以调用匿名内部类方法。
把匿名内部类作为类来调用方法
package demo.anonymous_inter_class3;
public class AnonymousInterCalss3 {
public static void main(String[] args) {
tea tea = new tea();
tea.test();
}
}
class stu{
public void say(){
}
}
class tea{
private int a = 999;
public void test(){
new stu(){
@Override
public void say() {
System.out.println("匿名内部类");
}
}.say();
}
}
把匿名内部类作为对象来调用方法
package demo.anonymous_inter_class3;
public class AnonymousInterCalss3 {
public static void main(String[] args) {
tea tea = new tea();
tea.test();
}
}
class stu{
public void say(){
}
}
class tea{
private int a = 999;
public void test(){
stu stu = new stu(){
@Override
public void say() {
System.out.println("匿名内部类");
}
};
stu.say();
}
}
(2)匿名内部类可以直接访问外部类的所有成员,包含私有的
package demo.anonymous_inter_class4;
public class AnonymousInterCalss4 {
public static void main(String[] args) {
Tea tea = new Tea();
tea.test();
}
}
class Stu{
public void say(){
}
}
class Tea{
private int a = 999;
private void printt(){System.out.println("外部类的私有方法");};
public void test(){
new Stu(){
@Override
public void say() {
System.out.println("匿名内部类");
}
public void eat(){
//(2)匿名内部类可以直接访问外部类的所有成员,包含私有的
System.out.println(a);
printt();
}
}.eat();
}
}
(3)不能添加访问修饰符,因为它的地位就是一个局部变量。
(4)作用域:仅仅在定义它的方法或代码块中。
(5)匿名内部类-----访问----->外部类成员
[访问方式:直接访问]
(6)外部其他类—不能访问----->匿名内部类(因为匿名内部类地位是一个局部变量)
(7)如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
package demo.anonymous_inter_class5;
public class AnonymousInterCalss5 {
public static void main(String[] args) {
Cellphone cellphone = new Cellphone();
cellphone.alarmclock(new Bell() {
@Override
public void ring() {
System.out.println("懒猪起床啦~");
}
});
cellphone.alarmclock(new Bell() {
@Override
public void ring() {
System.out.println("小伙伴上课辣~~");
}
});
}
}
interface Bell{
void ring();
}
class Cellphone{
public void alarmclock(Bell bell){
bell.ring();
}
}
9 成员内部类(1)上面匿名内部类整体作为实参
(2)编译类型为Bell,运行类型为匿名内部类
(3)优势:省去了要再写一个class类来实现接口【硬代码】,直接传入匿名内部类
(1)成员内部类是定义在外部类的成员位置,并且没有static修饰。
(2)可以直接访问外部类的所有成员,包含私有的
(3)可以添加任意访问修饰符(public、protected、默认、private),因为它的地位就是一个成员。
(4)作用域和外部类的其他成员一样,为整个类体。
(5)成员内部类-----访问---->外部类成员(比如:属性)
【访问方式:直接访问】
(6)外部类-----访问------>成员内部类
【访问方式:在外部类中,建立成员方法,在方法内创建对象,再访问】
(7)外部其他类-----访问---->成员内部类
方式一:通过在外部其他类中调用
方式二:在外部类中建立一个可以返回成员内部类的方法
package demo.member_inner_class;
public class MemberInnerClass {
public static void main(String[] args) {
//外部其他类MemberInnerClass访问---->成员内部类InnerClass
//方式一:通过在外部其他类中调用
OutClass outClass = new OutClass();
OutClass.InnerClass innerClass = outClass.new InnerClass();
innerClass.use();
//方式二:在外部类中建立一个可以返回成员内部类的方法
OutClass.InnerClass innerclass2 = outClass.getInnerclass();
innerClass.use();
}
}
class OutClass{
private int n = 999;
private void test(){System.out.println("外部类的test私有方法");}
//成员内部类
public class InnerClass{
public void use(){
System.out.println(n);
test();
}
}
public void printt(){
InnerClass innerClass = new InnerClass();
innerClass.use();
}
public InnerClass getInnerclass(){
return new InnerClass();
}
}
(8)如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
10 静态内部类(1)静态内部类是定义在外部类的成员位置,并且有static修饰
(2)可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员
(3)可以添加任意访问修饰符(public.protected、默认、private),因为它的地位就是一个成员。
(4)作用域同其他的成员,为整个类体。
(5)静态内部类-----访问---->外部类(比如:静态属性)
【访问方式:直接访问所有静态成员】
(6)外部类-----访问------>静态内部类访问方式:创建对象,再访问
(7)外部其他类-----访问----->静态内部类
package demo.staticinnerclass;
public class StaticInnerClass {
public static void main(String[] args) {
//外部其他类访问静态内部类的方式一
AA aa = new AA();
AA.Inner inner = new AA.Inner();
inner.test();
//方式二:
AA.Inner inner1 = AA.getinner();
inner1.test();
//方式三:
aa.use();
}
}
class AA{
private static int n1 = 888;
private int n2 = 999;
private static void test(){System.out.println("外部类的test方法");}
public static class Inner{
private int n1 = 777;
public void test(){
System.out.println("静态内部类的test方法");
//System.out.println(n2);//错误 非静态无法访问
System.out.println(n1);
AA.test();
}
}
public static Inner getinner(){
return new Inner();
}
public void use (){ //创建对象在访问静态内部类
Inner inner = new Inner();
inner.test();
}
}
(8)如果外部类和静态内部类的成员重名时,静态内部类访问的时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类.成员)去访问
内部类练习题:



