Java SE 是什么,包括哪些内容(十一)?

本文内容参考自Java8标准
前面博文中的内容完全体现了Java中面向对象思想,但是,Java毕竟是从C和C++中而来,肯定存在不用创建对象就能使用的代码环节,那么如何与必须创建对象的代码环节区分呢?就是通过static关键字。
再来回顾一下面向对象创建对象的内容:

  1. 首先需要根据实际情况创建类。
// 创建一个类
public class Person{
    //创建一个变量name代表姓名。
    private String name;
    //...其他的变量。
    //构造方法
    public Person(){}
    //...其他的构造方法
    //创建一个方法eat():
    public void eat(){
       //方法体
    }
    //...其他的方法
}
  1. 利用类创建类对象,并给对象取一个易识别的引用名称(也叫标识符)。
// 创建Person类对象p,p就是这个对象的引用名称(标识符).
    Person p = new Person();
  1. 利用引用名称(标识符)去调用变量或者是方法。
//修改变量
   p.name = "James";
// 调用方法
    p.eat()

之前所接触的Java面向对象代码编程中,无外乎以上三步。
如果Java所有的内容全部限定为以上三步,同时还必须创建对象,这样的话就过于受限了。
从前面的博文中我们知道了,一个类,只要是创建了一个对象,那么这个对象的引用名称是存储在堆栈上的,而实际的对象是存储在堆上的。并且每一个对象都含有相同的类变量以及方法。
那么static关键字有以下作用:

  1. 如果是修饰一个类(只能修饰内部类,不能修饰外部类):
// static修饰一个类,需要特别声明的是static只能修饰一个内部类,
//不能修饰一个外部类
//内部类和外部类的知识点请及时关注后期博文更新。
//外部类Person
public class Person{
     //内部类Child
     static class Child{}
}

static不能修饰外部类:

java 创建类 java创建类的关键字_java 创建类


static修饰内部类有什么用呢?答案可以很肯定的告诉你:

没什么用!

唯一的区别在于创建对象时候的代码:

用了static修饰:

// static修饰内部类
public class Person{
     //内部类Child
     static class Child{
        //内部类构造方法(内部类其实就是一个普通的类,只不过是写在了另一个类的内部而已)
        Child(){
             System.out.print("我是一个内部类!");
        }
     }
     //程序执行方法入口main方法
     public static void main(String[] args){
         //创建内部类Child的对象
         new Person.Child();
     }
}

用static修饰的内部类是可以直接用"外部类名称.内部类名称表示",因为这个内部类属于的是类,不属于对象,所以创建的形式就是"new 外部类名称.内部类名称()",也就是new Person.Child();

实际示例:

java 创建类 java创建类的关键字_java 创建类_02


没用static修饰:

// static修饰内部类
 public class Person{
      //内部类Child
      class Child{
         //内部类构造方法(内部类其实就是一个普通的类,只不过是写在了另一个类的内部而已)
         Child(){
              System.out.print("我是一个内部类!");
         }
      }
      //程序执行方法入口main方法
      public static void main(String[] args){
          //创建内部类Child的对象
          new Person.new Child();
      }
 }

如果内部类没有被static修饰,就不属于类了,属于的是对象,所以需要先创建外部类的对象,再用外部类的对象去创建内部类的对象:

首先是Person p = new Person();

再p.new Child();

简写就是:new Person().new Child();

实际示例:

java 创建类 java创建类的关键字_java 创建类_03


一般很少看到用static去修饰内部类,当然,如果这么写也没什么问题。

  1. static修饰变量:
    用static修饰了的变量和没用static修饰的变量区别很大。
    如果一个变量用了static修饰,无论你创建多少个对象,这个变量始终只有一 个!
    如果一个变量没有用static修饰,那么创建了多少个对象,这个变量就会有多少个。
    代码示例:
// static修饰变量
      //类Person
      public class Person{
          //变量name,代表姓名
          private String name;
          //变量total,代表总数,用static修饰
          private static int total;
          //构造方法
           public Person(){
                //每次创建对象的时候total都自增1;
                total++;
          }
          //程序执行的入口main方法
          public static void main(String[] args){
               new Person();
               new Person();
               new Person();
               System.out.println(total);
          }
      }

实际结果示例(有static修饰):

java 创建类 java创建类的关键字_内部类_04


实际结果示例(无static修饰):直接报错!因为没有与具体的对象关联。

java 创建类 java创建类的关键字_外部类_05


所以,如果你需要控制某一个变量的存储区域只有一个(与创建对象的数量无关),就可以用static关键字修饰它!

  1. static修饰方法:
    为什么会出现需要static修饰的方法?因为在一种极端的情况下,你调用方法的时候,不一定需要创建对象。我不知道使用"极端"修饰这种情况是否合适,不过严格来说,这确实是一种很特殊的情况。是什么情况呢?
    工具类!
    如果你正在创建的是一种工具类,它的方法全部都和工具有关,那么你在使用它的方法的时候,就不用创建它的对象,而是直接使用方法就行了。那么对应到代码里面是什么情况呢?
    我们来看一个最经典的工具类的代码:
    这个类就是:

System

源码:

变量全是static的:

java 创建类 java创建类的关键字_java 创建类_06


方法全是static的

java 创建类 java创建类的关键字_java 创建类_07


我想如果你接触了Java,你应该从来没有见过:

System s = new System()

吧。你见过的应该都是

System.out…/System.err…

所以可以得出如下的结论:
static修饰的方法可以直接使用"类名称.方法名称()"这种形式调用,而不用创建类对象,再用对象标识符调用。方便简洁。
所以static修饰一个方法仅仅是简化了方法的调用形式,而并没有对方法的功能产生影响。方法仍然是一个普通方法,一旦被调用,方法体可以正常执行。

  1. static修饰代码块: Java中有一种形式的执行优先级最高:代码块 代码块分两种,首先来看一下用static修饰了的代码块:静态代码块代码示例:

java 创建类 java创建类的关键字_代码块_08

  1. 只要产生了对这个类的任何一个部分的调用,都首先执行静态代码块,再执行对应调用的内容,所以静态代码块具有最高的优先级,你可以将需要最先执行的代码,比如某些基础工作,放进代码块中,但是有一点需要注意:代码块里的内容只会执行一次!!! 再来看一下没有static修饰的代码块:代码块的优先级确实要高于构造方法:

java 创建类 java创建类的关键字_java 创建类_09

这个是普通代码块,也需要注意,普通代码块也是只会执行一次的。 那么静态代码块和普通代码块的执行优先级如何呢?代码示例:

java 创建类 java创建类的关键字_外部类_10



从结果可以看出,静态代码块的优先级要高于普通代码块!