static 关键字-内部类

一、static 关键字

1.1 静态域

    如果把域定义成 static,每个类中只有一个这样的域,而每个对象 对于 所有的实例域 却都有自己的一份 拷贝 。比如: 需要给每个雇员赋予唯一的标识码:

class Employee
{
private static int nextID=1;
private int id;
}

    现在,每个雇员都有自己的 id 域,但这个类的所有实例将共享一个 nextid 域。换言之,如果有 1000 个 Employee 类对象,则有 1000 个 实例域 id,但是只有一个静态域 nextId;即使没有一个 雇员对象,静态域 nextId 也存在,它属于类,不属于任何独立的对象。

1.2 静态常量

    比如 Math.PI 、System.out 都是静态常量。

1.3 静态方法

    静态方法是一种 不能向对象实施操作的方法,不能访问实例域,但是可以访问自身类的静态域。
    可以使用对象访问静态方法。
    使用静态方法的情景:

  • 一个方法不需要访问对象状态,其所需参数都是通过显式参数提供。
  • 一个方法只需要访问类的静态域。
  • 做工厂方法。

    ❓静态内部类 与 普通内部类 的区别❓
静态内部类是不依赖于外部类的,也就说可以在不创建外部类对象的情况下创建内部类的对象。另外,静态内部类是不持有指向外部类对象的引用的,这个d读者可以自己尝试反编译class文件看一下就知道了,是没有 Outter this&0 引用的。

1.4 静态内部类

    像线程池ThreadPoolExecutor中的四种拒绝机制CallerRunsPolicy、AbortPolicy、DiscardPolicy、DiscardOldestPolicy就是静态内部类。
    与常规内部类不同,静态内部类可以有静态域 和 方法。
    静态内部类 不依赖于外部类实例对象 而被实例化;不能访问外部类的普遍成员变量;只能访问外部类中的静态成员 和 静态方法。

    

二、 内部类

    内部类是 定义在另一个类中的类。使用内部类的原因:

  • 内部类方法可以访问该类定义所在的作用域中的数据,包括私有的数据。
  • 内部类可以对同一个包中的其他类隐藏起来。
  • 当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较快捷。
        内部类可以用 private 、protected、public 、(default)、abstract、final、static 修饰。
         内部类中声明的所有 static 静态域必须是 final, 原因很简单,我们希望一个静态域 只有一个实例,不过对于每个外部对象,会分别有一个单独的内部类实例,如果这个域不是 final ,它就可能不是唯一的。
2.1 成员内部类

    成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象。
    为什么成员内部类可以访问外部类的成员呢?
    编译时,会把 成员内部类 单独编译成一个字节码文件,编译器会自动为成员内部类添加一个指向外部类对象的引用。

2.2 局部内部类

    可以在一个方法中定义局部类,例如:

public class OutterClass
{

  public void start()
  {
    //在方法中定义局部类
     class partClass implements ActionListener
       { 
           public void actionPerformed(ActionEvent event)
          {
             System.out.println("At the time,the time is"+new Date());
             }   
        }
   }
}

    局部类不能用 public 或 private 访问说明符进行声明。它的作用域被限定在声明这个局部类的块中。
    局部类有一个优势,即 对外部世界可以完全隐藏起来,即使
OutterClass 类的代码也不能访问它。除了 start() 方法,其他方法不知道 局部类 的存在。而局部类可以访问它们的外部类,还可以访问局部变量。

2.3 匿名内部类

    假设只创建这个类的一个对象,就不必命名了。这样的类称为 匿名内部类:

public class OutterClass
{

  public void start()
  {
  //创建一个 实现 ActionListener 接口的类的新对象
                   // ActionListener 是个接口
     partClass pc=new ActionListener
       { 
           public void actionPerformed(ActionEvent event)
          {
             System.out.println("At the time,the time is"+new Date());
             }   
        }
   }
}

    这样 创建了 一个 实现 ActionListener 接口的类的新对象 pc
,需要实现的方法 actionPerformed 定义在括号里。
    通常的语法格式:

new SuperType(construction parameters)
{
  inner class 
      method and data
}

     其实,SuperType 可以是接口,于是内部类就要实现 implements 这个接口,也可以是一个类,于是内部类就要扩展 extends 它。
    由于构造器的名字必须与类名相同,而匿名类没有类名,所以,匿名类不能有构造器。取而代之的是,将构造器参数传递给 父类 的构造器,尤其在内部类实现接口的时候,不能有任何构造参数
    ❓为什么局部内部类 和 匿名内部类 只能访问局部 final 变量❓
     局部内部类 和 匿名内部类 都会被编译成 class 文件,像局部内部类,其变量的生命周期随着方法执行完毕就结束了,所以 Java 采用复制的方法:如果局部变量的值在编译期间就可以确定,则直接在匿名内部里面创建一个拷贝。如果局部变量的值无法在编译期间确定,则通过构造器传参的方式来对拷贝进行初始化赋值。使用的变量只是值和方法中 局部变量 的值相等,与 方法中的局部变量 是完全独立的。
    如果在不同方法中 对 变量有修改,就会造成数据不一致,为了解决这个问题, 编译器就限定必须将 变量 限制为 final 类型,不允许对 变量 进行更改(对于引用类型的变量,是不允许指向新的对象),这样数据不一致性的问题就得以解决了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值