Java class 各种区别?一张图就够了

初学Java类的时候,有很多概念不清楚–外部类,内部类,静态嵌套类……等等一堆词语,都是干啥的?有啥区别?很不明白.专门花了一下午的时间,到自己写程序的时候,毫无信心.什么时候改用啥,甚是恐慌.因此专门花了一下午的时间,将The Java™ Tutorials ->Classes and Objects 仔细读了一遍,并做了些梳理与总结.

总的来说,Java中各种类的关系和特点可以用下面的图来表示:

这里写图片描述
这里写图片描述这里写图片描述

如上图所示,class可以分为两种:

  • 普通的class.这里为了和将要讨论的内部类相对应,称之为外部类.这只是我在总结的时候为了明显区分自己这么写的.
  • 嵌套类.就是在类的内部定义的类,而更具体的,嵌套类又可以再分为两种:
    • 非静态的嵌套类,习惯上称之为内部类.
    • 静态的嵌套类.

区分静态内部类和非静态类的方法很简单,顾名思义,就是看看定义类的时候,有没有用static 这个关键字修饰.他们两个最主要的区别就是内部类可以直接访问外部类的成员,不论是private 的还是public 的,而静态嵌套类是不能直接访问外部类的实例成员,注意是实例成员,对于类成员,静态嵌套类是可以直接访问的.例如:

  1 import java.text.*;
  2 import java.util.*;
  3 public class Test{
  4         private String mem = "I am the static menber of outer";
  5         public static void main(String... args){
  6                 new Test().test();
  7         }
  8         public void test(){
  9 
 10                 NestedStaticClass nsc =new NestedStaticClass();
 11                 nsc.accessOuterStaticMember();
 12         }
 13         static class NestedStaticClass{
 14 
 15                 public void accessOuterStaticMember(){
 16                         System.out.println(mem);
 17                 }
 18         }
 19 }

静态嵌套类是不能直接访问外部类Test 的私有成员是实例成员mem 的,这样做是不能通过编译的,而如果在mem 前面用static 修饰,这样做就没问题了.
此外,内部类是不能定义静态成员的.但是可以有静态常量.为什么会这样呢?如果把他们看做外部类的一个成员,这就容易理解了.我们知道,被static修饰的是类成员,而类成员是不能直接访问实例成员的,必须通过实例进行引用.而内部类是用于和类的实例进行交互的,如果我们在它内部定了静态成员,这就矛盾了.
而静态嵌套类因为有static 修饰,使得可以解脱束缚,这样的性质,就使得它可以和普通类一样使用,不用收外部类的限制,可以直接通过new Outer.Inner() 的方式实例化,而内部类inner class 是不可以这样的,它只能通过外部类的实例来引用.

内部类又有两个特殊形式:

  • 局部类.
  • 匿名内部类.

局部类,就是定义在语句块内的一个类,可以在函数中,亦可以在for 循环等的循环体中.只要有花括号{} 圈起来都行.匿名内部类,就是一个没有名字的局部类,严格的说,其实匿名内部类就是一个表达式而已.
它们既然是内部类的特例,那么就具有内部类的性质,例如,可以直接访问外部类的成员,不能定义静态变量等.此外,由于它们是定义在语句块中,它们就不能有public 这些修饰符修饰了.
值得一提的是,局部类和匿名内部类如果要访问局部变量,局部变量必须是final 修饰的,也就是常量.从jdk 8开始,只要是实际上的赋值后不在改变的变量都可以.这是因为它们所引用的局部变量是“俘获”的.什么意思,就是它会复制一份在自己的堆里面.从虚拟机的角度来看,不管什么类,在虚拟机看来都是独立的一个类,因此,局部类需要使用局部变量时会对其进行复制,在自己的空间保存一份副本.
还有,匿名内部类是不能有构造函数的,因为名字都没有,更何谈构造函数?要是真的有,他得叫啥?
嵌套内部类使用的基本事项基本就是这样了,下面来简单说说类的一些继承性质.
Java类是单继承的.也就是所有类只能有一个直接父类(Object除外),简单的说,就是extends 后只能有一个类,不过这也有例外,就是如果是interface,extends 后面是可以跟任意个interface的,是不是很神奇?当然,我们要说的并不是这些,我们想说的是继承的一些性质,主要有三点:

  • 子类复写父类非静态方法,子类对象赋值给父类引用,调用方法版本是子类的方法;子类复写父类静态方法(隐藏),子类对象赋值给父类引用,调用的方法是父类的方法.特别需要注意的是,当实现接口时,对于接口中的default,static 子类对象赋值给接口的引用,调用方法版本是子类实现的的方法.
  • 子类中只要有与父类名字相同的field,就会把父类的屏蔽,不管类型是否相同.

最后,在interface所有成员默认是公有的,因此public 可以省略不写,编译器会自动加上.

发布了45 篇原创文章 · 获赞 4 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/ZM_Yang/article/details/69264773