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” 博客,转载请与作者联系!