public class Main {}//外部其他类
public class Outer //外部类
{
public class Outer{} //内部类
}
前言:内部类的知识,我感觉是有点难的,细节很多,我的建议是先看多几遍视频再来看一下文章,我相信只要不放弃,看多几次,总能学会,并熟悉的。最后就是看这篇文章可以先跳到总结,再回来看细节
局部内部类
局部内部类一般是在 类中的函数 或 代码块 中 再创建一个类
public class Outer //外部类
{
//在函数中的内部类
void func()
{
class Inner
{
}
}
//在代码块中的内部类
{
class Inner2
{
}
}
}
1.局部内部类,可以访问外部类中所有成员,包括私有
public class Outer {
private int var1 = 10; //外部类私有变量
private void f() //外部类私有函数
{
System.out.println("hello world!");
};
void func() //外部类的 func()
{
class Inner //内部类
{
void print() //内部类的 print
{
System.out.println("var1 = " + var1);//内部类访问外部类属性
f();//内部类访问外部类函数
}
}
}
}
2. 外部类 访问 局部内部类成员:在局部套着内部类的函数创建对象,再访问
public class Main
{
public static void main(String[] args)
{
Outer outer = new Outer();
outer.func();
}
}
public class Outer
{
private int var1 = 10;
private void f()
{
System.out.println("hello world!");
};
void func() //外部类的 func()
{
class Inner //内部类
{
void print() //内部类的 print
{
System.out.println("var1 = " + var1);
f();
}
}
//在套着内部类的这个局部,创建内部类对象,再调用
Inner inner = new Inner();
inner.print();
}
}
这里在 套着内部类的 外部类函数 func() 里面创建了内部类的对象,然后调用print函数。然后看到主函数 new 了一个外部类对象,外部类对象 调用 了 func()函数 看到下面 new 了一个内部类对象并且调用了内部类的 print 函数
3. 外部其他类 不能 访问局部内部类
public class Outer
{
private int var1 = 10;
void func() //外部类的 func()
{
class Inner //内部类
{
void print() //内部类的函数 print
{
System.out.println("var1 = " + var1);
}
}
}
}
4.局部内部类的成员和外部类成员重名,内部类访问外部类成员遵循就近原则,如果想调用外部类的成员,必须用 外部类.this.成员名
public class Main {
public static void main(String[] args)
{
Outer outer = new Outer();
outer.func();
}
}
public class Outer
{
int var1 = 10;//外部类的var1
void func() //外部类的 func()
{
int var1 = 20;//和外部类同名的var1;
class Inner //内部类
{
void print() //内部类的函数 print
{
System.out.println("var1 = " + var1);
}
}
//调用内部类成员
Inner inner = new Inner();
inner.print();
}
}
这里可以看到结果是 20,所以同名就遵循就近原则
把 print 中的 var 修改成 outer.this.var1:
System.out.println("var1 = " + Outer.this.var1);
可以看到输出 var1 是 10,所以同名了想调用外部类的成员,就用 外部类.this.成员名,这个的意思是 外部类对象的引用.成员
匿名内部类
1.基本使用原理
先观察一手代码
基于接口的
public class Main
{
public static void main(String[] args)
{
new Outer().func();
}
}
class Outer {
void func()
{
U u1 = new U()
{
@Override
public void use()
{
System.out.println("重写了 U 接口");
}
};
u1.use();
}
}
interface U {
public void use();
}
解释
这里可以看到 它 new 了一个 U,但是这个接口是不能 new 的,但是它可以 new, 原理是这样的:
U u1 = new U(){}:底层给了一个看不见的类,然后实现了 U 接口, 然后把这个对象实例化赋给 u1class 底层给的名 implements U { @Override public void use() { System.out.println("重写了 use"); } } ---- 然后把这个类实例化再赋给 u1
基于类的
class U
{
public void use() {
System.out.println("原有use");
}
}
代码把接口 U 改成了类, 其他一样的, U u = new U(){},底层是这样的
class 底层给的名 extends U { @Override public void use() { System.out.println("重写了 use"); } }
然后把这个类实例化赋给 u
现在我们分析一下 编译类型 和 运行类型
U u1 = new U()
这里 编译类型很明显是 U,然后看运行类型,它其实不是 U,因为我们在上面讲过了它的底层是 创建一个系统命名的类 然后 继承类 或者 实现接口,再实例化对象,赋给左边。所以它实际的运行类型,是 匿名内部类类型
2. 匿名内部类可以,直接访问外部类,所有成员,包括私有
3. 外部其他类 不能访问 匿名内部类
4. 如果外部类和内部类成员重名时,内部类访问的话遵循就近原则,如果想访问外部类成员,可以用 外部类名.this.成员
因为匿名内部类,本身也是在局部的,所以这几点都和局部内部类一样的,这里不再演示了
成员内部类
成员内部类就是类中再弄一个类
class Outer
{
class Inner
{
}
}
1. 成员内部类可以直接访问外部类,所有成员,包括私有
2.成员内部类和外部类有重名属性或方法,还是用 外部类.this.成员
这几点上面演示过,这里不再演示了
3. 外部类 访问 成员内部类,要创建对象再访问:外部类中弄个方法,方法里创建成员内部类对象,再访问
public class Main {
public static void main(String[] args) {
Outer outer = new Outer();
outer.useInner();
}
}
class Outer {//外部类
private int n1 = 10;
private void func()
{
System.out.println("hello world!");
};
class Inner {//成员内部类
public void say() {
System.out.println("n1 = " + n1);
func();
}
}
void useInner(){
Inner inner = new Inner();
inner.say();
}
}
4. 外部其他类 访问 成员内部类
第一种方法
public class Main {//外部其他类
public static void main(String[] args) {
Outer o = new Outer();
Outer.Inner i = o.new Inner();
}
}
class Outer {
class Inner{}
}
先要实例化一个外部类对象,然后 Outer.Inner i 的意思就是 Outer 类里的 Inner 类 类型。 o.new Inner():这个我感觉不好理解,只能死记了。
第二种方法
public class Main {//外部其他类
public static void main(String[] args) {
Outer o = new Outer();
Outer.Inner i = o.getInner();
}
}
class Outer {
class Inner{}
public Inner getInner() {
return new Inner();
}
}
直接在外部类,写一个方法,返回 Inner 类型的引用,这个感觉好理解一点。
静态内部类
静态内部类,就是成员内部类加了 static
class Outer
{
static class Inner
{
}
}
1. 静态内部类,可以直接访问,外部类所有静态成员,包括私有,是静态成员,不是所有成员!!!,非静态成员不能直接访问
2. 外部其他类 访问 静态内部类
第一种方法
public class Main {
public static void main(String[] args) {
Outer.Inner i = new Outer.Inner();
}
}
class Outer {
static class Inner
{
}
}
静态的东西 可以直接 通过类名访问,静态的类是的独立的。 所以:Outer.Inner i 就是 Outer 里的 Inner 类 类型,new Outer.Inner(),就是直接 new 一个 Outer 里的 Inner 类。这里讲的还是很抽象,不过没关系,看多就变成常识了。
第二种方法
public class Main {
public static void main(String[] args) {
Outer o = new Outer();
Outer.Inner i = o.getInner();
}
}
class Outer {
static class Inner
{};
public static Inner getInner() {
return new Inner();
}
}
这个和普通成员内部类一样,通过函数返回对象
3.如果外部类和静态内部类重名,遵循就近原则,不过想访问外部类成员,则可以使用 (外部类名.成员)
public class Main {
public static void main(String[] args) {
Outer.Inner i = new Outer.Inner();
i.print();
}
}
class Outer {
static int var = 10;
static class Inner {
static int var = 20;
void print() {
System.out.println("外部类var: " + Outer.var);
}
};
}
总结
-
成员内部类 和 静态内部类 本质就是个成员,我觉得可以把 静态内部类 说成 成员静态内部类,这两可以看成一套
-
局部内部类,匿名内部类 本质是个局部成员,我觉得可以把 匿名内部类 说成 局部匿名内部类,这两可以看成一套
-
局部的一套 外部其他类 不能 访问局部内部类
-
成员的一套 外部其他类 可以 访问成员内部类
-
局部和成员那套:想用外部类访问内部类,必须想办法先实例化对象,再访问
-
内部类,都可以直接访问外部类成员,包括私有。在外部类和内部类出现重名的时候,访问外部类成员的方式都是 外部类名.this.成员。但是静态内部类不一样,它可以直接外部类名.成员。因为这是静态的特性
一只卑微的大一牛马,水平有限,博客主要用来复习,有错的话,欢迎评论区鞭打我