new int 34 至少有一维要明确给定而其它维则可在以后再确定。
例如 int i new int 3 是一个合法的声明。
除了在变量名及方法名后跟方括号这种C风格的声明之外Java语言允许方括号跟在数组类型之后下面两行是等价的 int iarray int iarray 同样地方法声明也一样 byte fint n byte fint n 运行时检查下标保证它们是合法的 int a new int 10 a51 a1a0a2 a-14 // 运行时引发一个ArrayIndexOutOfBoundsException数组下标越界异常 a102 //运行时引发一个ArrayIndexOutOfBoundsException数组下标越界异常 数组的大小必须使用整数表达式 int n float arr new floatn1 数组的长度可通过.length 查找 int a new int 103 println a.length //打印出10 println a0.length //打印出3。
3.3.1 数组细节 定义的数组都是Object类的一个子类的实例在类的层次结构中有一个被称为Array的子类它有一个实例变量“length”。
对每一个基本类型都有一个相应的Array的子类。
同理每一个类也都有一个相应的Array子类存在。
例如 new Threadn 创建一个Thread 的实例。
如果类A是类B的超类那么A是B的超类见下图 Object Array A int float A B B 因此可以把数组赋给一个Object变量。
Object o int anew int 10 oa 并且可通过强制类型转换把object变量赋给一数组变量。
aint o Array类本身不能显式地产生子类。
4. 类 类class是传统面向对象编程模型的象征。
它们支持数据抽象以及实现对数据的约束在Java中每一个新的类创建一个新类型。
要想得到一个新的类程序员必须首先找到一个已有的类新类即在这个已有类的基础上构造称之为派生derived。
派生出的类亦称为原来类的子类而这个类我们称为超类super class。
类的派生具有传递性 如果B是A的子类C是B的子类则C 是A的子类。
一个类的直接超类以及指示这个类如何实现的界面interface在类的声明中由关键字extends及implements标出。
如下示黑体表示关键字 doc_ comment modifer class ClassName extends Superclassname implements interface interface class body 举例 / 2 dimension point / public class Points float xy ...... / printable point / class PinttablePoint extends Points implements Printable ...... public void Print 所有的类均从一个根类 Object中派生出来。
除Object之外的任何类都有一个直接超类。
如果一个类在声明时未指明其直接超类那么缺省即为Object。
如下述 class Point float xy 与下面写法等价 class Point extends Object float x y Java语言仅支持单继承通过一个被称作“界面”的机制来支持某些在其它语言中用多继承实现的机制详见“界面”一节。
Java之所以没有采用C的多继承机制是为了避免多继承带来的诸多不便例如可能产生的二义性编译器更加复杂程序难以优化等问题。
4.1 类类型之间的强制转换 Java语言支持在两个类型之间的强制转换因为每个类即是一个新的类型。
Java支持类类型之间的强制转换如果B是A的子类那么B的一个实例亦可作为A的实例来使用虽然不需要显式的转换但显式转换亦是合法的这被称作拓宽widening。
如果A的一个实例想当作B的实例使用程序员就应写一个类型转换叫作削窄narrowing的强制。
从一个类到其子类的强制转换在运行时要作例行的检查以确保这个对象就是其子类的一个实例或其子类之一。
兄弟类之间的强制类型转换是一个编译错误类的强制转换的语法如下nbsp nbsp classname ref 其中classname是要转换的目的类而ref是被转换的对象。
强制转换仅仅影响到对象的引用而不会影响对象本身。
然而对实例变量的访问却受到对象引用的类型的影响。
一个对象从一个类型到另一类型的强制转换后可以使同一变量名对不同的实例变量访问。
class ClassA String name quotClassAquot class ClassB extends ClassA //ClassB是ClassA的子类 String namequotClassBquot class AccessTest void test ClassB bnew ClassB println b.name //打印 ClassB ClassA a aClassAb println a.name //打印 ClassA 4.2 方法 方法method是可施于对象或类上的操作它们既可在类中也可在界面中声明。
但是他们却只能在类中实现Java中所有用户定义的操作均用方法来实现。
类中的方法声明按以下方式 Doc_ comment
Access Specifiers ReturnType methodNameparameterList method body本地的native及抽象的方法没有体部分 除构造函数可以无返回类型外其余的方法都有一个返回类型。
如果一个不是构造函数的方法不返回任何值那么它必须有一个void的返回类型。
参数表由逗号分隔的成对的类型及参数名组成如果方法无参数则参数表为空。
方法内部定义的变量局部变量不能隐藏同一方法的其它变量或参数。
例如 如果一个方法带以名为i的参数实现且方法内又定义一个名为i的局部变量则会产生编译错误例如 class Rectangle void vertex int iint j for int i0 i … 方法体内循环语句中声明的i是一个编译错误。
Java语言允许多态方法命名即用一个名字声明方法这个名字已在这个类或其超类中使用过从而实现方法的覆盖overriding及重载overloadding。
所谓覆盖是对继承来的方法提供另一种不同的实现。
而重载是指声明一个方法 它与另外一个方法有相同的名字但参数表不同。
注 返回类型不能用来区别方法即在一个类的范围内具有相同的名字相同的参数表包括个数、位置及类型的方法必须返回相同的类型。
若这样的两个方法有不同的返回类型将会产生一个编译错误。
4.2.1 实例变量 实例变量instance variables是指那些在类内声明但在方法的作用域之外尚未被static标记的变 参照 “静态方法变量及初始化”段。
而在一个方法的作用域之内声明的变量是局部变量。
实例变量可以有修饰符见修饰符。
实例变量可以是任何的类型并且可以有初始值。
如果一个实例变量无初始值它将被初始化成0。
布尔型变量被初始化成flase对象被初始化成null。
下面是一个实例变量j具有初始化值的例子 class A int j 23 …… 4.2.2 this 和super变量 在一个非静态方法的作用域内this这个名字代表了当前对象。
例如一个对象可能需要把自己作为参数传给另一个对象的方法 class MyClass void Method OtherClass obj … obj.Method this … 不论何时一个方法引用它自己的实例变量及方法时在每个引用的前面都隐含着“this”。
如 class Foo int abc ...... void myPrint print a quotnquot // aquotthis.aquot ...... super变量类似于this变量。
this变量实际上是对当前对象的引用它的类型就是包含当前正在处理的方法的类。
而super变量则是对其超类类型对象的引用。
4.2.3 设置局部变量 方法都要经过严格的检查以确保所有的局部变量在方法内声明的变量在被引用之前已设初被初始化之前就使用局部变量是一个编译错误。
4.3 覆盖方法 要想覆盖overiding一个方法必须在声明这个方法的类的子类中声明一个与它具有相同名字相同返回类型以及相同参数表的方法。
当子类的实例调用这个方法时被调用的是新定义的方法而不是最初的那个。
被覆盖了的方法可通过super变量来调用如下 setThermostat… //指覆盖的方法 super. setThermostat… //指被覆盖的方法 4.4 重载的认定 重载overload的方法与已有的某个方法同名但是变元的个数及/或类型不同重载的认定是要决定调用的是哪一个方法在认定重载的方法时不考虑返回类型。
方法可以在同一类的内部重载类内部方法声明的顺序并不重要。
可同时改变变元个数和类型来实现方法的重载。
编译器认定相匹配的方法时以最低的类型转换开销为准。
只有具有相同名字及相同变元个数的方法才会优先考虑。
所有变元都必须转换是匹配方法时的最大开销。
有两种变元类型是必需考虑的对象类型和基本类型。
对象类型间转换的开销的大小指类树上实在参数的类与原型参数的类之间连线的个数。
只考虑拓宽型转换对象类型转换的详细信息请参 阅“类之间的强制类型转换”。
对于类型完全匹配的变元无须进行转换它们的开销为零。
基本类型的转换开销按下表计算开销为零是严格匹配。
to byte short char int long float double byte 0 1 2 3 4 6 7 short 10 0 10 1 2 4 5 from char 11 10 0 1 2 4 5 int 12 11 11 0 1 5 4 long 12 11 11 10 0 6 5 float 15 14 13 12 11 0 1 double 16 15 14 13 12 10 0 注开销 gt10 易引起数据丢失。
一经认定某一匹配方法是哪种转换开销编译器则选用转换开销最小的匹配。
如果有多于一个方法其最小开销相同则匹配有二义性要出编译时的错误。
例如 class A int method Object o Thread t int methodThread tObject o void gObject oThread t methodot //调用第一个方法 methodto //调用第二个方法 methodtt //有二义性编译出错 4.5 构造函数 构造函数constructor是提供初始化的专用方法。
它和类的名字相同但没有任何返回类型。
构造函数在对象创建时被自动地调用它不能被对象显式调用。
如果你想在包package之外调用构造函数就将构造函数设为“public”。
构造函数也可以用不同个数和类型的参数重载就象其它的方法被重载一样。
class Foo int x float y Foo x0 y0.0 Foo int a xa y0.0 Foo float a x0 ya Foo int afloat b xa yb static void myFoo Foo obj1new Foo //调用Foo Foo obj2new Foo4 //调用Foo int a Foo obj3new Foo4.0 //调用Foo float a Foo obj4new Foo44.0 //调用Fooint a float b 超类的实例变量由调用超类的或当前类的构造函数初始化。
如果在代码中没有指定由谁初始化则调用的是超类中的无参数的构造函数。
如果一个构造函数调用了这个类或其直接超类的另一个构造函数这个调用必须是构造函数体的第一条语句在调用构造函数之前实例变量不引用。
调用直接超类的构造函数如下 class MyClass extends OtherClass MyClass someParamenters / 调用父类构造函数 / superotherParameters … … 调用当前类的构造函数如下示 class MyClass extends OtherClass MyClass someParameters … MyClassotherParameters /调用当前类的构造函数该函数有指定的参数表/ this someParameters … … 下面的Foo和FooSub类的方法中使用构造函数的例子 class Foo extends Bar int a Fooint a //隐含调用Bar this.aa Foo this 42 //调用Foo42代替Bar class FooSub extends Foo int b FooSub int b super13 //调用Foo13 去掉此行将调用Foo this.bb 4.6 用new运算符创建对象 类是用来定义对象的状态和行为的模板对象是类的实例。
类的所有实例都分配在可作无用单元回收的堆中。
声明一个对象引用并不会为该对象分配存储程序员必须显式地为对象分配存储但不必显式删除存储无用单元回收器会自动回收无用的内存。
分配对象存储用new运算符。
除了分配存储之外new还初始化实例变量调用实例的构造函数。
构造函数是初始化对象的一种方法见“构 造函数”下面的例子是分配并初始化ClassA的一个实例 a new ClassA 以下构造函数是带有参数的例子 b new ClassA32 分配的第三种形式允许以串表达式形式提供类名字字符串在运行时刻求值new返回一个Object类型的对象再转换成所希望的类型。
b new quotclassquotquotAquot 这种情况下调用构造函数时无需参数。
4.6.1 无用单元收集 无用单元收集器Garbage Collector使存储管理的许多方面变得简单、安全。
程序不需要显式释放内存它是自动处理的。
无用单元收集器不会释放正在被引用的内存只释放那些不再被引用的空间。
这就防止了悬挂指针和存储漏洞leak。
它也使设计人员从系统的存储管理中解脱出来。
4.6.2终止 Java的构造函数完成一个对象初始化工作Java的终止finalization方法则完成和析构函数类似的功能但与C不同之处是它可显式调用。
虽然Java的无用单元的回收功能可以自动地释放对象所占有的资源.
上一篇:
Nginx源代码目录分析
下一篇:
成都住宅小区施工组织设计及预算参考资料