内部类的定义与使用
一、内部类的基本概念
定义:从内部类这个名字来看,就是在一个类的里面的一个类。其实质就是,在一个类的内部进行其他类结构的嵌套操作。
下面看一段通过内部类实现的功能:
class Outer1{
private String msg="外部类的属性";
//下面定义一个内部类
class Inner{
public void print(){//内部类的一个普通方法
System.out.println(msg);//直接调用外部类的属性
}
}
//在外部类中定义一个方法,该方法负责产生内部类对象并且调用内部类的print()方法
public void fun(){
Inner in=new Inner();//创建一个内部类的对象
in.print();//通过内部类的对象访问内部类的方法
}
}
public class TestOuter1{
public static void main(String[] args){
Outer1 out = new Outer1();//外部类对象
out.fun();//外部类方法
}
}
从上面代码的结果我们可以看到内部类的使用使得我们的程序逻辑变得比较混乱了,但是它也有一些功能,内部类可以直接访问外部类的方法、属性,不会受到私有的限制。
如果将上面的内部类变成普通类的话访问的属性就会受到限制了:
class Outer1{
private String msg="外部类的属性";
public String getMsg(){
return msg;
}
//在外部类中定义一个方法,该方法负责产生内部类对象并且调用内部类的print()方法
public void fun(){
Inner in=new Inner();//创建一个内部类的对象
in.print();//通过内部类的对象访问内部类的方法
}
}
class Inner{
public void print(){//一个叫内部类的普通类的一个普通方法
Outer1 out=new Outer1();
//不在本类的对象是不可以直接访问私有属性的,必须通过get、set方法才可以访问
System.out.println(out.getMsg());//error直接调用外部类的属性
}
}
public class TestOuter1{
public static void main(String[] args){
Outer1 out1 = new Outer1();//外部类对象
out1.fun();//外部类方法
}
}
从上面的结果我们可以看出,如果只是普通类的话对于私有属性的访问我们不可以直接通过对象访问,必须通过set、get封装的方法,对私有属性进行访问。
二、内部类问什么会存在
既然内部类会让我们的程序结构变得混乱,可是为什么它还是会存在呢,总共有四条原因,下面我们将一 一解答:
1.在内部类可以访问该类定义所在作用域中的数据(就是在包含这个类中的所有属性、方法),包括私有属性。
2.内部类对同一包中的其他类是隐藏的(在同一个包中的其他类是访问不到内部类的)。
3.内部类可以实现java单继承的缺陷。
4.内部类可以解决定义一个回调函数且可以不写大量的代码,使用的是匿名内部类。
栗子:内部类实现多继承
//内部类实现多继承
class A{
private String name = "A类的私有属性";
public String getName(){
return name;
}
}
class B{
private int age = 20;
public int getAge(){
return age;
}
}
class Outer{
//定义一个内部类继承类A
private class InnerClassA extends A{
public String name(){
return super.getName();
}
}
//定义一个内部类继承类B
private class InnerClassB extends B{
public int age(){
return super.getAge();
}
}
public String name(){
return new InnerClassA().name();
}
public int age(){
return new InnerClassB().age();
}
}
public class TestOuter1{
public static void main(String[] args){
Outer out = new Outer();
System.out.println(out.name());
System.out.println(out.age());
}
}
三、内部类与外部类的关系
1.对于非静态内部类,内部类对象的创建依赖外部类的实例对象,在没有外部类实例之前是无法创建内部类的对象的;所以我们在创建内部类的对象的时候需要先创建外部类的对象。下面举一个栗子:
//InnerA:
//非静态内部类要在其它的地方使用时——>创建对象的方式如下:
//InnerA 是成员内部类 ,是非静态内部类
//InnerA 对象内部 引用了一个外部类对象的引用
//创建的时候需要先创建一个外部类,通过外部类创建内部类属性;但是在使用的时候完全不受控制
Outer.InnerA innerA = new Outer().new InnerA();
System.out.println(innerA.getName());
2.内部类是一个相对独立的实体,与外部类不是一对一的关系
3.内部类是可以直接访问外部类的属性的,包括私有属性;但是外部类不可以直接访问内部类的元素
栗子:内部类可以直接访问外部类的元素
//内部类可以直接访问外部类的元素
class Outer{
private String outName;
private int outAge;
class Inner{
private int innerAge;
public Inner(){
Outer.this.outName="i am outer class";
Outer.this.outAge=2;
}
public void display(){
System.out.println(outName);
System.out.println(outAge);
}
}
}
public class TestOuter1{
public static void main(String[] args){
Outer.Inner inner = new Outer().new Inner();
inner.display();
}
}
4.外部类可以通过创建内部类的对象来访问内部类的元素
//外部类通过内部类的对象来访问内部类
class TestOuter1{
class Inner{
private String msg2;
public String getMsg2(){
return msg2;
}
public void setMsg2(String msg2){
this.msg2=msg2;
}
public void print(){
System.out.println("这是内部类的方法");
}
}
//外部类的一个公有方法调用内部类的私有属性以及方法
public void fun(){
Inner inner = new Inner();//在外部类中创建内部类的对象
inner.print();//通过内部类的对象访问内部类的方法
inner.setMsg2("内部类属性");//通过内部类对象访问内部类的属性
System.out.println(inner.getMsg2());
}
public static void main(String[] args){
TestOuter1 outter= new TestOuter1();
outter.fun();
}
}
四、内部类
1.内部类的分类
在java中内部类主要分为四类:
a.成员内部类
b.静态内部类
c.方法内部类
d.匿名内部类
下面将对这四种类型的外部类进行一 一详解;在对他们进行详解之前我们先学习两种情况下创建内部类的方法:
(1)在使用内部类的时候(就是不在内部类里面)创建内部类对象
语法:
外部类.内部类 内部类对象=new 外部类().new 内部类();
Outter.Inner inner=new Outter().new Inner();
(2)在外部类的内部创建内部类(成员内部类)对象
语法:(在外部类内部创建内部类对象就和普通类创建内部类对象是一样的)
内部类 内部类对象=new 内部类();
Inner in=new Inner();
2.对于以上内部类的四种类型进行详解
(1)成员内部类
成员内部类就是我们前面所看到的一般内部类:
class Outer{
class Inner{
}
}
在成员内部类中我们需要注意:不要出现任何static修饰的属性、方法;成员内部类是依赖于外部类的,创建成员内部类的对象需要先创建外部类的对象才可以创建成员内部类的对象。
外部类.内部类 内部类对象=new 外部类().new 内部类();
Outter.Inner inner=new Outter().new Inner();
(2)静态内部类
静态内部类见名思意,我们之前学习的所有叫静态的都是被static修饰过的,所以我们的静态内部类也不例外,静态内部类也是被static修饰的内部类。我们的静态内部类和非静态内部类最大的区别在于我们的非静态内部类在编译完成之后会保留着一个引用指向外部类,但是静态内部类却没有,所以也就意味着:
静态内部类的创建不依赖外部类,可以直接创建;
同样它也遵循静态的性质,静态内部类不可以访问外部类的非静态方法和非静态属性;
在外部类中创建内部类的语法:
外部类.内部类 内部类对象 = new 外部类.内部类();
对以上两种内部类的创建语法进行分析可以发现,在创建成员内部类和静态内部类的最大区别在于一个创建了外部类,一个没有创建外部类。
(3)方法内部类
方法内部类的意思就是在外部类的方法中的类,也叫做局部内部类;方法内部类和成员内部类基本差不多,唯一的区别就是作用于不同了,方法内部类的作用于仅在这个方法方法内,出了这个方法内部类就无效了。方法内部类的存在是为了解决一些比较复杂的问题,当我们在解决某个问题的时候遇到某个比较难的问题就将它括起来成为方法内部类,当然我们肯定只希望这个内部类仅仅解决这个问题,不希望其他的访问到它,不然的话就起不到这个作用了。
我们要求方法内部类满足以下几点:
*方法内部类不允许使用访问权限的修饰符:private,public,protected;
*方法内部类对外完全隐藏,除了创建这个类的方法可以访问意外其他的都不可以访问;
*方法内部类要想使用方法形参,该形参必须用final声明(在IDK8以后形参变为隐式声明即默认声明了);——笔试题中常常在这考
方法内部类的栗子:
//3.使用方法内部类
class Outer {
private int num;
public void display(int test){
class Inner{
private void fun(){
num++;//默认值0+1=1
System.out.println(num);
System.out.println(test);
}
}
new Inner().fun();//这条语句只有在这个方法中才有效,出了这个方法就无效了。这个就是方法内部类
}
}
public class TestOuter1{
public static void main(String[] args){
Outer out = new Outer();
out.display(20);
}
}
(4)匿名内部类
匿名内部类实际上就是一个没有名字的方法内部类,所以匿名内部类对于方法内部类所受的约束也同样需要遵循。除此之外,它还得注意:(都得记住)
*匿名内部类不可以使用权限修饰符;
*匿名内部类对外完全隐藏,只有创建这个类的方法才可以访问;
*匿名内部类也可以引用方法形参。此形参也必须用final声明;
*匿名内部类必须继承一个抽象类或者实现一个接口;
*匿名内部类中不可以有任何的静态方法或成员;
*匿名内部类是没有构造方法的,因为它没有类名;
栗子:如何使用匿名内部类
//4.如何使用匿名内部类
interface MyInterface{
void test();
}
class Outer{
private int num;
public void display(int para){
//匿名内部类,实现了MyInterface接口
new MyInterface(){
//方法重写
public void test(){
System.out.println("匿名内部类"+para);
}
}.test();
}
}
public class Test {
public static void main(String[] args){
Outer Outer = new Outer();
outer.display(20);
}
}
匿名内部类的特点:
*破坏了程序结构;
*方便进行私有属性访问(外部类也可以访问内部类的私有属性);
*如果发现类名称上出现了 . ,那么应该立马想到