目录
一.内部类
1.什么是内部类
内部类:一个类嵌套在另一个类的内部,称这个嵌套类为内部类.
public class Outter {
//内部类
class Inner{
}
}
2.内部类存在的原因
内部类是封装的一种体现,
人类和心脏类的关系就是一种内部类和外部类的关系
汽车发动机和汽车关系也是一种内部类和外部类的关系
3. 内部类的分类
根据定义的位置和使用的关键字的不同,可以分为以下四种内部类
- 成员内部类
- 静态内部类
- 方法内部类
- 匿名内部类
4.内部类的作用
- 内外部类可以更方便的访问彼此的私有属性
- 可以打破单继承的局限
具体的表现在下面慢慢的具体分析
二.成员内部类
1.基本概念
成员内部类:直接定义在类中,不加static定义的内部类就称为成员内部类
2.成员内部类的注意点
提示:可以把成员内部类类比为类中的成员方法
1.成员内部类可以用private方法进行修饰
我们都知道我们平常使用的类是不可以使用private关键字进行修饰的,因为这样在外部就无法访问到这个私有的类了,定义显得没有必要了.
但是成员内部类是可以用private关键字修饰的,表示在外部无法直接创建私有的成员内部类
public class Outter {
private String name;
//私有的内部类
private class Inner {
}
}
2.成员内部类可以直接访问外部类的私有属性
在内部类Inner中,我们直接可以访问外部类的私有属性和私有方法,直接调用,不需要创建对象,类比为成员方法直接调用类中的私有属性和私有方法
直接调用的name相当于Outter.this.name
直接调用的fun()相当于Outter.this.fun()
public class Outter {
private String name;
//内部类
private class Inner {
private int num;
private void test() {
//直接在成员内部类直接访问外部类的私有属性
System.out.println(name);
fun();
System.out.println("inner的test方法");
}
}
private void fun() {
System.out.println("外部类的fun方法");
}
}
3.外部类可以通过对象访问内部类的私有属性
外部类中是不可以直接访问内部类的属性和方法的,但是我们可以通过创建内部类的对象来访问内部类的私有属性和方法.
如果是一个普通的类,内部定义了私有的属性和方法,我们即使创建了对象,也不可以访问内部的私有属性和方法,但是外部类中定义了内部类的对象,我们是确实可以访问到内部类的私有属性和方法的
public class Outter {
private String name;
//内部类
private class Inner {
private int num;
private void test() {
//直接在成员内部类直接访问外部类的私有属性
System.out.println(name);
System.out.println("inner的test方法");
}
}
private void fun() {
//产生内部类的对象
Inner inner = new Inner();
//外部类中访问内部类的属性
System.out.println(inner.num);
inner.test();
System.out.println("外部类的fun方法");
}
public static void main(String[] args) {
Outter outter = new Outter();
outter.fun();
}
}
main方法的输出
0
null
inner的test方法
外部类的fun方法
4.成员内部类中不可以定义static属性和方法
类比于成员方法,在成员方法中是不可以定义static的属性的,因为方法的调用需要对象来调用,而static的变量是不需要对象调用的,这显然是矛盾的
3.产生内部类的对象
1.在外部类的内部产生内部类的对象
直接new出来内部类的对象即可
类名称 引用名称=new 类名称();
Inner inner = new Inner();
2.在外部类的外部产生内部类的对象
注意:如果成员内部类私有(private),无法在内部类的外部产生内部类的对象
外部类名称.内部类名称 内部类引用=new 外部类名称().new 内部类名称();
public class Test {
public static void main(String[] args) {
//在外部类的外部产生内部类的对象
Outter.Inner inner = new Outter().new Inner();
}
}
类比于成员方法:成员方法必须通过类的对象调用
同理:要产生内部类的对象,首先要产生外部类的对象
三.静态内部类
1.基本概念
静态内部类:直接定义在类的内部,使用staic关键字修饰,就成为静态内部类
2.静态内部类的注意点
注意:可以把静态内部类类比于静态方法
1.静态内部类可以通过对象访问内部类的私有属性
直接new外部类的对象,然后便可以访问其私有的属性和方法
因为静态内部类不需要依赖外部类的对象产生而产生,因此静态内部类中不能直接访问外部类的方法和属性,必须通过外部类的对象来访问,但是可以直接访问外部类的静态属性和方法
public class StaticOutter {
private String name;
static class inner {
private int num;
public void test() {
//通过外部类的对象访问其私有属性和方法
StaticOutter staticOutter = new StaticOutter();
staticOutter.fun();
System.out.println(staticOutter.name);
}
}
private void fun() {
System.out.println("外部类的fun方法");
}
}
2.静态内部类可以直接访问外部类的静态属性和方法
public class StaticOutter {
private String name;
static int age;
static class inner {
private int num;
public void test() {
//直接访问外部类的静态属性和方法
System.out.println(age);
method();
//通过外部类的对象访问其私有属性和方法
StaticOutter staticOutter = new StaticOutter();
staticOutter.fun();
System.out.println(staticOutter.name);
}
}
public static void method() {
System.out.println("外部类的method方法");
}
private void fun() {
System.out.println("外部类的fun方法");
}
}
3.外部类通过对象访问静态内部类中的私有属性和方法
和成员内部类中的外部类访问内部类一样
public class StaticOutter {
private String name;
static int age;
static class Inner {
private int num;
public void test() {
//直接访问外部类的静态属性和方法
System.out.println(age);
method();
//通过外部类的对象访问其私有属性和方法
StaticOutter staticOutter = new StaticOutter();
staticOutter.fun();
System.out.println(staticOutter.name);
}
}
public static void method() {
System.out.println("外部类的method方法");
}
private void fun() {
//外部类通过对象访问静态内部类中的私有属性和方法
Inner inner = new Inner();
System.out.println(inner.num);
System.out.println("外部类的fun方法");
}
}
4.静态内部类中可以定义静态变量也可以定义成员变量
静态内部类可以看做相当于一个普通的类,只不过嵌套在了外部类的里面了而已
public class StaticOutter {
private String name;
static class Inner {
private int num;
static String address;
public static void method(){
System.out.println("静态内部类的静态方法method");
}
public void test() {
//通过外部类的对象访问其私有属性和方法
StaticOutter staticOutter = new StaticOutter();
staticOutter.fun();
System.out.println(staticOutter.name);
}
}
private void fun() {
//外部类通过对象访问静态内部类中的私有属性和方法
Inner inner = new Inner();
System.out.println(inner.num);
System.out.println("外部类的fun方法");
}
}
3.产生静态内部类的对象
1.在外部类的内部产生静态内部类
和成员内部类一样
类名称 引用名称=new 类名称();
Inner inner = new Inner();
2.在外部类的外部产生静态内部类
外部类名称.内部类名称 内部类引用=new 外部类名称.内部类名称();
静态内部类不需要外部类的对象,因此不需要创建外部类的对象
public class Test {
public static void main(String[] args) {
//在外部类的外部产生静态内部类的对象
StaticOutter.Inner inner = new StaticOutter.Inner();
}
}
四.成员内部类和静态内部类的对比
1.实际案例
成员内部类和外部类相当于人类和心脏,心脏的产生不能离开人的产生
而静态内部类和外部类相当于车和发动机,发动机可以立刻车独立存在
2.两者差异
成员内部类中包含了外部类的对象,能直接访问外部类的成员属性,不能定义静态属性
静态内部类中没有包含外部类的对象,不能直接访问外部类的成员属性,能定义静态属性和成员属性
3.内部类的作用
1.经过以上的分析,我们可以总结出内部类的一大作用就是可以直接访问外部类的私有属性和方法
2.我们知道一个子类只能继承一个父类,我们如果使用内部类,便可以写出类似多继承的子类,规避单继承的局限性,此时外部类中就包含了A和B的所有属性和方法
class A {
}
class B {
}
public class InnerClassExtends {
class InnerA extends A {
}
class InnerB extends B {
}
}
4.编译后的class文件
Outter是外部类,Inner是内部类,中间用$符分隔开
五.方法内部类
1.基本概念
方法内部类:直接定义在方法中的类
2.方法内部类的注意点
注意:方法内部类可以类似于参数
1.方法内部类不能使用任何的访问修饰符
public class MethodInner {
private String name;
public void fun() {
//在方法中定义的类技术就是方法内部类
class Inner {
}
}
}
2.方法内部类的声明周期只在方法调用的过程中存在
方法调用结束之后自动销毁,方法内部类对方法外部完全隐藏
public class MethodInner {
private String name;
public static void fun() {
//在方法中定义的类技术就是方法内部类
class Inner {
private int num;
private void test() {
//可以访问到外部类的私有
System.out.println(new MethodInner().name);
}
}
//可以通过对象访问到方法内部类的私有属性和方法
//在这个方法之外无法new Inner对象
Inner inner = new Inner();
inner.test();
System.out.println(inner.num);
}
}
3.方法内部类中的访问范围
方法内部类中的方法是否需要new外部类取决于外部方法是static还是普通的
public class MethodInner {
private String name;
public void fun() {
//在方法中定义的类技术就是方法内部类
class Inner {
private int num;
public void test() {
//可以访问到外部类的私有
System.out.println(name);
}
}
}
}
public class MethodInner {
private String name;
public static void fun() {
//在方法中定义的类技术就是方法内部类
class Inner {
private int num;
public void test() {
//可以访问到外部类的私有
System.out.println(new MethodInner().name);
}
}
}
}
4.方法内部类形参不可改变
若方法内部类使用方法的形参,这个参数必须为形式上的参数(不能在类中修改该参数的值,JDK8之后),JDK8之前必须显式的定义为final
在方法内部类中调用了方法的形参,在方法内也不能改变其值;我们可以思考一下为什么.因为如果我们在方法内部类中调用了方法的形参,而此时我们在方法中修改了形参的值,无法确定调用的形参的值是原始的,还是修改过后的形参的值
总结:在方法内部类中只能访问方法内的参数,不能修改其值
方法形参是否有final取决于方法形参中是否使用了形参
六.匿名内部类
1.基本概念
匿名内部类:定义在方法之中,主要是在方法的形参上使用,这个类没有名字,一般默认继承一个类或者一个接口
2.匿名内部类的示例
interface IMessage {
void print();
}
public class NonNameMethod {
public void fun() {
new IMessage() {
@Override
public void print() {
}
};
}
}
上边的结构相当于这样进行转换的
3.匿名内部类的使用 ----参数使用匿名内部类
public static void main(String[] args) {
compare(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return 0;
}
});
}
public static void compare(Comparator c) {
System.out.println("compare方法");
}
上面的compare方法需要传入一个接口对象,这个时候我们需要传入一个接口的实现类,实现向上转型,这个时候我们就需要使用匿名实现类了