《Java组件设计》第三章 预备知识

3         预备知识

本章主要讲解一些组件开发中常用的技术,作为后续章节讲解组件设计的预备知识。
本章假设读者已经熟悉了 Java 语言的基本语法,并且熟练使用 Java 语言至少 3 年,因此,简单的语法知识不再讲述,仅讲解一些高级主题。

3.1             Java语法深入

本节对 Java 语法中一些高级主题进行讲解。

3.1.1       static

3.1.1.1     static 变量

本质上讲, static 关键字声明了一个全局变量。
尽管 Java 是一门纯面向对象的语言,语言规范中没有全局变量这种说法,但 static 声明的变量,从本质上就等同于 C C++ 语言中的全局变量。整个应用程序就一个变量实例,任何对 static 变量进行的更改,在程序的其它地方都可见。
举个例子如下:
public class StaticExample {
  public static int counter;
}
counter 是个整型变量,前面用 static 关键字修饰后,就变成了一个全局变量,在程序的代码执行之前,这个 counter 变量就已经在内存中存在了,而且是唯一的一份实例。
counter 静态变量是在 StaticExample 类中声明的,但实际上 counter 变量是独立于 StaticExample 的任何实例的。也就是说,程序没有创建任何 StaticExample 类的实例时, counter 已经存在。程序创建 100 StaticExample 实例时, couner 在内存中仍然是一份,而不是 100 份。当程序中创建的 StaticExample 类的实例都被虚拟机垃圾回收了, counter 还存在。因此静态变量的生命周期,可以认为程序的第一行代码执行之前,就已经在内存中准备好,在程序的最后一行代码执行完毕,静态变量还在内存中存在。静态变量独立于任何对象,包括声明静态变量的类实例对象。
对简单类型是这样,对复杂类型 ( 对象类型 ) 也是这样。
静态变量的这种特性,经常被用在单实例的类实现中,例子如下:
public class Logger {
  // 构造函数声明为 private, 这样就不能在类的外部用 new 来创建对象
  private Logger() {}
 
  private static Logger logger = null;  // 单实例
 
  // 暴露给外界调用的方法
  public static Logger getLogger() {
    if (null == logger) {  // 判断静态实例是否初始化,如没有就创建
       logger = new Logger();
    }
 
    return logger; // 返回全局唯一的实例
  }
 
  // ……  其它方法声明
}

3.1.1.2     static 方法

如果一个类方法,仅依赖方法的传入参数、其它 static 变量,则此方法不依赖于声明方法的类实例,则此方法应该声明为 static ,表示此方法是类方法,而非实例方法。例子如下:
public class ConvertUtil
  public static int toInt(String s) {
    return Integer.parseInt(s);
  }
}
toInt 方法的实现,仅依赖于方法传入的参数 s ,不依赖 ConvertUtil 对象的成员变量,因此 toInt 方法是个类方法,不是个实例方法,因此用 static 来修饰 toInt 方法的声明。这样,调用者调用时的代码就象下面这样:
    int iValue = ConvertUtil.toInt(str);
如果不用 static 修饰,则调用者的代码就需要修改为如下:
    ConvertUtil util = new ConvertUtil();
     int iValue = util.toInt(str);
但实际上, toInt 方法根本就不需要创建一个 ConvertUtil 类的实例,这个对象是个浪费。
组件设计中,常用的工具类方法,基本都是 static 声明的。

3.1.1.3     static

一个普通的 Java 类声明,用 static 修饰,是非法的,编译器会提示出错。这一点,与 C++ 的静态类的概念是完全不同的。在 C++ 中,一个类的声明用 static 修饰,则这个类中的所有成员变量和成员函数都是静态方法,独立于对象存在。
对于嵌套类的声明,可以用 static 修饰,则为另外的含义,在后续的嵌套类中进行讲解。

3.1.2       嵌套类

一个类的声明,是在另外一个类中,这种在类中声明的类叫嵌套类,也叫类中类、内部类。例子如下:
public class Outer {
  private String outerId;
  private Inner inner = new Inner();
 
  public String getId() {
    // 访问内部类的私有成员
    return outerId + "-" + inner.innerId;
  }
 
  public void setId(String id) {
    String[] strArray = id.split("-");
    outerId = strArray[0];
    inner.setId(strArray[1]);        // 调用内部类的私有方法
  }
 
  private void printStr(String str) {
    System.out.println(str);
  }
 
  // 内部类定义
  public class Inner {
    private String innerId;
    private String getId() { return innerId; }
   
    private void setId(String id) {
       innerId = id;
    }
   
    protected void printId() {
       String str = "outerId=" + outerId + ", innerId=" + innerId;     // 访问外部类的私有成员
       printStr(str);    // 访问外部类的私有方法
    }
  }
}
总结如下:
1)     内部类可以访问外部类的任何成员变量,包括外部类的私有成员变量;
2)     内部类可以调用外部类的任何成员函数,包括外部类私有成员函数;
3)     外部类可以访问内部类的任何成员变量,包括内部类的私有成员变量;
4)     外部类可以调用内部类的任何成员函数,包括内部类的私有成员函数;
因此,对于内部类的成员变量和成员函数,用private, protected, public, package 修饰,就如同没有这些修饰词一样。
另外,内部类是不能独立于外部类而单独存在的,对象构造的顺序是由外向内,先生成外部类,然后生成内部类。

3.1.3       静态嵌套类

嵌套类,在类声明的时候用 static 修饰,就成了静态嵌套类。静态嵌套类与普通嵌套类是完全不同的。这里, static 的唯一作用,就相当于一个分隔符,将内部类和外部类隔离开来,使内部类独立于外部类单独存在。也就是说,内部类对外部类没有任何的依赖关系。而普通的内部类,是必须依赖于外部类而存在的。
因此,外部类与静态内部类之间的关系,就和两个独立的类之间的关系相同,二者之间互相访问,与两个独立类之间的访问规则相同。因此,用 private, protected, public, package 修饰,将直接影响可访问性。示例如下:
public class OuterClass {
 
  private String outerId;
  private StaticInner inner = new StaticInner();
 
  public String getId() {
    // return outerId + "-" + inner.innerId(); // 私有成员,不允许访问
    return outerId + "-" + inner.getInnerId(); // 公有方法,可以访问
  }
 
  public void setId(String id) {
    String[] strArray = id.split("-");
    outerId = strArray[0];
    inner.setInnerId(strArray[1]); // 公有方法,可以访问
  }
 
  private void printStr(String str) {
    System.out.println(str);
  }
 
  public static class StaticInner {
    private String innerId;
    public String getInnerId() {
       return innerId;
    }
 
    public void setInnerId(String innerId) {
       this.innerId = innerId;
    }
   
    public void printId() {
        // 无法访问外部类的私有成员
       // String str = "outerId=" + outerId + ", innerId=" + innerId;    
       // printStr(str);   // 无法访问外部类的私有方法
       OuterClass outer = new OuterClass();
       outer.printStr(innerId); // 同一 package 中,可以访问私有方法
    }
  }
}

本文出自 “expert” 博客,转载请与作者联系!

你可能感兴趣的:(java,模式,组件,设计,休闲)