第5章:Java高级类特性4:static_设计模式_代码块_final


时间:2018-07-25 作者:魏文应


一、static 关键字

static 修饰类属性

用static来修饰类的成员变量,也被称为 类变量。我们可以先看下面代码:

class SportsMan{
    String name;
    static String nation;
    
    @Override
    public String toString() {
        return "SportsMan [name=" + name + ", nation=" + nation + "]";
    }
}
public class TestSprotsMan {
    public static void main(String[] args){
        SportsMan s1 = new SportsMan();
        SportsMan s2 = new SportsMan();
        s1.name = "小强";
        s1.nation = "中国";
        System.out.println(s1);
        System.out.println(s2);     
    }
}

输出结果如下:

SportsMan [name=小强, nation=中国]
SportsMan [name=null, nation=中国]

你会发现,s1 和 s2 的 name 属性值不一样,而 nation 属性值是一样的。这说明,static 修饰的成员变量,在由该类创建的所有对象中,static 成员变量,只有一份。假设使用SportsMan类,创建了 s1、s2、s3、s4、s5、s6这些实例,修改任何一个实例的static成员变量,会导致 该类的所有实例 的static成员变量的值发生改变。而 没有 static 修饰 的成员变量,各自有各自的存储单元,不会发生修改实例的成员变量,导致另一个成员变量的值也被修改的情况

  • 内存存储情况

这也说明了,使用 static 修饰的属性,不依赖实例 而存在,只要有类,就有它。所以可以使用 类名.属性 的形式来调用它:

SportsMan.nation = "美国";
System.out.println(SportsMan.nation);

static 修饰类方法

static 修饰的类的方法,也被称为 类方法。和static修饰的类属性一样,类方法有以下特点:

  • 随着类的加载而加载。
  • 内存中也是独有一份。
  • 不依赖类的实例而存在,可以使用 类名.方法 的形式来调用。
  • 内部可以调用 static 修饰的属性和方法。
  • 内部不可以调用 没有 static 修饰的属性和方法。

下面是其应用实例:

class SportsMan{
    static int name;

    public void show(){
        System.out.println("Show:Hello World!");
        show2();        // 类内直接使用
    }

    public static void show2(){
        System.out.println("Show2:Hello World!");
        name = "魏文应";
    }
}
public class TestSprotsMan {
    public static void main(String[] args){
        SportsMan s = new SportsMan();
        s.show();               // 需要创建类的实例

        SportsMan.show2();      // 外面直接调用
    }
}

上面代码中,没有 static 修饰的方法 show() 只能通过 对象.方法 的方式调用,使用该方法前需要创建一个对象。而有 static 修饰的方法 show2() 不但可以使用 对象.方法 的形式调用,还可以使用 类.方法 的形式调用。

二、设计模式

什么是设计模式?就像铁匠,打了一辈子的铁,最后总结了一些经验,这些经验使得打铁更省力,打出的铁性能更好。设计模式也是一样,Java 程序员在必须大量的程序以后,发现了一些比较好的写法,并且这些写法比较常用。将这些写法总结成标准模式,就叫做设计模式。

单例设计模式

什么叫单例模式?单例模式就是有一个类,允许这个类创建一个对象 。下面是一种叫做 饿汉式 单例模式:

class Singleton{
    // 1.私有化构造器,使得类的外部不能够调用此构造器。
    private Singleton(){
    }
    // 2.在类的内部创建一个类的实例
    private static Singleton instance = new Singleton();
    // 3.私有化此对象,通过公共的方法来调用
    public static Singleton getInstance(){
        return instance;
    }
}
public class TestSingleton {
    public static void main(String[] args){
        Singleton s1 = Singleton.getInstance();
        Singleton s2 = Singleton.getInstance();
        System.out.println(s1 == s2);
    }
}

私有化构造器,在类内部创建当前类对象,使用 static 修饰类方法,这样,外部只能通过 类名.方法 的形式返回实例的引用。而这个实例的引用只有一个,那就是 instance ,从而达到这个类只能创建一个实例的效果。另外,还有一种叫做 懒汉式 的单例模式:

class Singleton1{
    private Singleton1(){
        
    }
    private static Singleton1 instance = null;
    public static Singleton1 getInstance(){
        if(instance == null){
            instance = new Singleton1();
        }
        return instance;
    }
}
public class TestSingleton1 {
    public static void main(String[] args){
        Singleton1 s1 = Singleton1.getInstance();
        Singleton1 s2 = Singleton1.getInstance();
        
        System.out.println(s1 == s2);
    }
}

懒汉模式,同样要私有化构造器,类内部在第一次使用 getInstnce 类方法 时,创建一个实例,此后不再创建新的实例。这样的好处是,在需要是在创建实例。缺点是,在多线程中,可能有多个线程进入 if(instance == null) 内部,导致 instance = new Singleton1(); 语句多次被执行。

三、main()方法的使用

在类内部,main方法格式如下:

public static void main(String[] args){
}

它是程序的入口。我们可以对它进行 传参测试

public class TestMain {
    public static void main(String[] args) {
        for(int i = 0; i < args.length; i++){
            System.out.println(args[i]);
        }
    }
}

在 Eclipse 中, 依次点击 Run As -> Run Configurations -> Arguments , 在Program Arguments 中,输入你希望向main() 中传入的参数,比如我这里 传入参数 为三个字符串:

魏文应、小强、宇航
  • main参数输入设置

然后点击 Run 按钮即可。

四、类变量的成员之四:初始化块

什么是初始化块?初始化块就是在一个类中, 用 { } 大括号直接括起来的内容,比如:

class Order{
    {
        System.out.println("我是初始化块");
    }
}

在类中,关于属性的操作,顺序是:

1、先是默认的初始化。
2、显示的初始化或者代码块内初始化。
3、构造器赋值操作。
4、创建对象以后,外部调用赋值操作。

比如,下面对类的属性进行赋值操作:

class Order{
    private int orderId = 1000;
    // 初始化块,非静态代码块
    {
        orderId = 1001;
        System.out.println("我是非静态代码块1");
    }

    {
        orderId = 1002;
        System.out.println("我是非静态代码块2");
    }

    public Order(int orderId) {
        super();
        this.orderId = orderId;
    }

    public void setOrderId(int orderId) {
        this.orderId = orderId;
    }
}
public class TestOrder {
    public static void main(String[] args) {
        Order o1 = new Order(1004);
        System.out.println(o1);
    }
}

首先创建了orderId成员变量,默认初始化 orderId = 0 。然后是我们代码中,显示初始化 orderId = 1000,然后是 代码块 { }orderId = 1001,代码块可以有多个,所以在代码块2中,再次赋值 orderId = 1002 。在然后就是在 构造器中 赋值,最后可以在 外部 赋值。

注意:显式初始化和代码块,它们处于同一优先级别,也就是说,它们在类中出现的先后,是影响赋值的先后的。 比如下面代码:

class Order{
    {
        orderId = 1001;
    }
    private int orderId = 1000;
}

首先 orderId = 0, 然后 orderId = 1001,然后才是 orderId = 1000

static 静态代码块

什么是静态代码块?在类中,使用 static{ } 的代码块。比如下面代码:

class Order{
    static{
        System.out.println("我是静态初始化块");
    }
}

静态代码块的执行,要早于非静态代码块,和在类中的位置无关。注意:静态代码块中,调用的属性和方法都需要是类方法和类属性,也就是static修饰的方法和属性

五、关键字 final

final 表示最终的。可以修饰 属性、方法、类

final 修饰属性

final修饰属性时,赋值以后 值就不可以再修改,相当于常量:

final int PI  = 3.141592563;

既然是常量,那么 final 修饰的成员变量,建议使用 全大写 字母命名。final 修饰的属性,必须显式的赋值。赋值还可以再 代码块、构造器中赋值,但是,赋值操作只能有一次。

class Test{
    final int PI;
    {
        PI  = 3.141592563;
    }
}
class Test{
    final int PI;
    
    public Test(){
        PI  = 3.141592563;
    }
}

final 修饰方法

final 修饰的方法,就不能对它进行重写了:

class Test{
    public final void method1(){    
    }

//  public void method1(){  
//  }
}

比如上面代码,method1() 方法被 final 修饰,那么method1() 方法就 不能再进行重写 了。

final 修饰类

被final 修饰的类,就不能对它进行继承了:

final class Test{
}

那么下面的操作是 不被允许的

class Person extends Test{
}

从上面可以看出,Test 被 final 修饰以后,就 其它类就不能去继承它

你可能感兴趣的:(第5章:Java高级类特性4:static_设计模式_代码块_final)