




已阅读5页,还剩27页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
3.5 方法的调用方法定义的目的,就是要给其他人使用。多数情况下,使用方法需要进行显示的方法调用。方法被调用之后,就会执行方法体内部的语句,完成预定义的功能。3.5.1 方法调用的形式根据方法的调用者与被调用的方法所处的位置,方法调用的形式可以分为两种: 调用者和被调用方法位于同一类中,形式如下:this.方法名(实际参数列表)在大多数情况下,关键字this可以省略。 调用者位于被调用方法所在类的外部,形式如下:对象名.方法名(实际参数列表) 或者 类名.方法名(实际参数列表)实际参数列表是对应方法的形式参数列表,可以是0个或多个变量或表达式,如果超过一个,需用逗号分隔。下面是方法调用的两个例子。【例3.14】 同一类中调用方法示例。/-文件名invokeMethod.java,程序编号3.24-public class invokeMethod public void showMsg() System.out.println(This is showMsg method); public void callOther() showMsg(); /调用类中的另外一个方法,这里也可以写成this.showMsg() public static void main(String args) /创建对象 invokeMethod ob = new invokeMethod(); ob.callOther(); /调用callOther()方法 程序的输出如下:This is showMsg method在程序3.24中,方法callOther()和方法showMsg()处在同一个类中,所以调用后者时,直接使用方法名就可以。令人比较疑惑的地方是在main()方法中,此处调用callOther()方法使用了看似比较麻烦的办法:先创建一个对象ob,在用“对象名.方法名()”的格式来调用该方法,这似乎是多此一举。实际上,在这里,这么做是必须的。main()方法是一个静态方法,它由系统来调用。系统在调用它的时候,并没有创建一个invokeMethod的对象,而callOther()和showMsg()方法都是实例方法,它们被调用时,都必须有对象的存在。所以必须在main中先创建一个对象ob,才能调用这两个方法。从这一点来看,main方法虽然处在invokeMethod类的内部,但它的表现却如同在类的“外部”一样。这么解释,读者可能还会有疑惑:为什么callOther()又能够直接调用showMsg(),难道它能保证在调用后者时,对象已经存在?答案确实如此,因为callOther()本身是实例方法,它在被执行时,一定是有对象存在的。基于这个前提,它才能够直接调用showMsg()方法。【例3.15】 外部类调用方法示例。这里仍然利用程序3.24,另外再写一个类来使用invokeMethod类中的两个方法。/-文件名invokeOther.java,程序编号3.25-public class invokeOther public static void main(String args) invokeMethod ob = new invokeMethod(); /创建对象 ob.callOther(); /调用callOther()方法 %注意:需要将invokeMethod.java和invokeOther.java两个方法放在同一个目录下面,然后分别编译。后面如无特殊说明,需要用到两个或两个以上文件的,都必须放在同一目录下编译。程序3.25和程序3.24的输出结果完全一样。细心的读者还会发现,在invokeOther类中的main()方法和invokeMethod类中的main()方法代码完全一样。在3.7和3.8节中,还将进一步解释这一现象。在invokeOther类中,还可以调用showMsg()方法,形式还是ob.showMsg()。读者可以自己改动程序3.25查看效果。3.5.2 方法调用的参数在定义一个方法时,程序员可能会根据需要列出一个参数表,这些参数被称为形式参数,简称为形参。在调用方法时,需要调用者提供与之相匹配的参数表,被称为实际参数,简称为实参。这里的匹配有两个条件: 实参和形参的个数要相等。 实参和形参对应位置上的数据类型要相容。即数据类型相同,或者实参可以做自动类型转换转换成形参类型。图3.5 方法调用的传值过程在方法调用发生时,系统会将实参的值按照位置关系一个一个传递给形参,即第一个实参传给第一个形参,第二个实参传给第二个形参,这个过程中,不会考虑形参和实参的名字。如图3.5所示。由于在Java中存在两种类型的数据:基本类型和复合类型。这两种类型的数据作为参数传递时,是有区别的。本节将分别介绍这两种情况。1基本类型作为参数当方法的参数是基本类型(包括整型、浮点和布尔型)时,它是通过传值方式进行调用的。这种传递方式的特点是: 它所传递的实参的值是一个副本。 单值传递。实参本质上是一个可求值的表达式,它所求出来的值是一个基本类型。 单向传递。方法内部可以修改形参的值,但这种修改不会影响到对应的实参。直观来看,传值过程相当于一个赋值过程,实参是右值,形参是左值。它们发生联系只在调用的那一瞬间,以后二者之间再无关系。【例3.16】 单向传值示例。/-文件名invokeByValue.java,程序编号3.26-public class invokeByValue public void tryChange(int ix) ix = ix * 2; /企图改变参数的值 public void showDiffer() int ix = 10; System.out.println(调用tryChange方法之前,ix= + ix); /测试是否能改变实参的值 tryChange(ix); System.out.println(调用tryChange方法之后,ix= + ix); public static void main(String args) invokeByValue va = new invokeByValue(); va.showDiffer(); 程序的输出如下:调用tryChange方法之前,ix=10调用tryChange方法之后,ix=10从本例中可以看出,尽管在tryChange()方法中,改变了形参ix的值,但对于实参ix并没有影响。从这个例子还可以看出,形参实际上是一个局部变量,它的作用域仅限于定义它的方法体内部。实参的名字是否和它相同都没有影响。单向传值可以防止程序员在无意的情况下改变实参的值,起到了降低程序间数据耦合度的作用。但在某些情况下,单向传值却会阻碍某些功能的实现。比如,要写一个方法实现两个参数交换值的功能。初学者可能会写成下面这个样子:public void swap(int a, int b) int t=a; a=b; b=t;然后这样来调用它:swap(a,b);很不幸,调用过后,会发现,a和b的值没有任何改变。因为在方法swap中交换的只是形参a和b的值,这对于实参a和b来说,没有任何影响。实际上,在Java中,没有任何简单的方法能够实现上述交换两个基本变量的值,而只能把上面这段代码写在需要交换的地方。2复合类型作为参数如果形式参数不是基本类型,而是复合类型,比如类类型,那么实参和形参的表现行为和基本类型的参数会有一些区别。如果实参是一个类的对象,那么在调用相应的方法时,系统会将该对象的地址值传递给形参。例如,有一个类onlyTest,actual是它的一个对象作为实参,form是它定义的形参对象,则调用时的传值情形如图3.6所示(假定类实例在内存中的存储地址为0x00ff)。在Java中虽然没有“指针”这一概念,程序员也不需要掌握它。但在系统内部,仍然是存在指针的。图3.6就是指针运用的示例。actual和form指向了同一个对象实例,其中任何一个变量改变类实例中的值,都会对另外一个变量有所影响。对象的传值过程,其实是借用了C/C+中指针传值的方法,造成的效果也完全相同。下面这个例子展示了对象传值的效果。【例3.17】 对象传值示例。/-文件名onlyTest.java,程序编号3.27-public class onlyTest private int x = 0; /设置成员变量x的值 public void setX(int ix) x = ix; /获取成员变量x的值 public int getX() return x; 下面这个程序使用上面这个类,分别声明了一个实参和一个形参。/-文件名invokeByObject.java,程序编号3.28-public class invokeByObject public void (onlyTest form) int t = form.getX(); /获取对象form的成员变量x的值 form.setX(t*2); /改变对象form的成员变量x的值 public void onlyTest actual = new onlyTest(); actual.setX(100); System.out.println(调用tryChange方法之前,x= + actual.getX() ); /测试是否能改变actual的成员变量值 tryChange(actual); System.out.println(调用tryChange方法之后,x= + actual.getX() ); public static void main(String args) invokeByObject va = new invokeByObject(); va.showDiffer(); 在程序3.28中,showDiffer()先定义一个actual对象,并将成员x的值置为100。而后调用方法tryChange(),它的形参form接受actual的值,根据图3.6所示内容,它们将共用同一个对象。在tryChange()中改变了form的x值,这一改变,对actual也是有效的。程序的输出印证了这一点:调用tryChange方法之前,x=100调用tryChange方法之后,x=200由于C+中提供了传值调用和引用调用两种方式,于是有些程序员也认为Java的对象参数是采用的引用调用。这其实是一种误解,Java采用的是传地址值的调用方式,在某些情况下,虽然和引用调用效果相同(比如上例),但在另外一些情形下,还是可以看出两者的区别。下面这个例子说明了这一区别。【例3.18】 对象传地址值而非引用示例。这里仍然使用例3.17中的类onlyTest,再另外编写一个程序trySwap。/-文件名trySwap.java,程序编号3.29-public class trySwap /企图交换a和b的值 public void swap(onlyTest a, onlyTest b) onlyTest temp; temp = a; a = b; b = temp; /测试能否交换实参的值 public void showDiffer() onlyTest ox = new onlyTest(); /创建两个对象 onlyTest oy = new onlyTest(); ox.setX(100); oy.setX(200); System.out.println(调用swap()方法之前的值:); System.out.println( ox.x = + ox.getX() + , oy.x = + oy.getX(); /测试是否能交换ox和oy的值 swap(ox,oy); System.out.println(调用swap()方法之后的值:); System.out.println( ox.x = + ox.getX() + , oy.x = + oy.getX(); public static void main(String args) trySwap va = new trySwap(); va.showDiffer(); 在方法swap()中,形参是两个onlyTest的对象。如果是引用调用,那么交换这两个对象的值,将对实参ox和oy产生影响。程序实际运行后输出结果如下:调用swap()方法之前的值: ox.x = 100, oy.x = 200调用swap()方法之后的值: ox.x = 100, oy.x = 200从以上输出结果中可以看出,ox和oy的值没有受到丝毫影响,因此它不是引用调用。调用过程可以用图3.7和图3.8来说明。 图3.7 调用swap()时的传值过程 图3.8 执行swap()之后的情形补充说明一下:若有对象A和B,执行语句:A=B,则A和B都指向了同一个对象,它们的行为与上述参数传递的行为完全相同。%注意:通过上述分析可以看出,在Java中,虽然没有出现显示的指针,也没有指针这个概念,但用普通类声明的变量,本质上和C/C+中对象指针是一样的。而且,Java中也没有和C+中的引用类型完全等效的概念。最后总结一下方法参数的使用情况: 方法不能修改一个基本数据类型的参数; 方法可以改变一个对象参数的状态; 方法不允许让一个对象参数引用一个新的对象。3.5.3 隐含参数this回顾3.4.3小节中的例3.13,当方法中的局部变量和成员变量同名时,局部变量会屏蔽掉同名的成员变量。为了访问该成员变量,需要使用“this.成员变量”的形式。这个this是Java定义中的一个关键字。为了让程序员能够在方法中使用this,Java会将this作为一个隐含的参数传递给每一个实例方法。它其实是指向当前对象的一根指针,直观理解,它就是表示“本对象”的意思。this作为隐含参数传递,最重要的作用是区分各个对象所拥有的成员。先来回顾3.5.2小节程序3.27中的类onlyTest,它拥有一个成员变量x,两个方法setX()和getX()。程序员可以使用这个类来创建若干个对象,这些对象分别拥有自己的成员变量,相互之间不会干扰。如例3.19所示。【例3.19】 使用类onlyTest创建多个对象示例。/-文件名useOnlyTest.java,程序编号3.30-public class useOnlyTest public static void main(String args) onlyTest oa = new onlyTest(); onlyTest ob = new onlyTest(); oa.setX(100); /将成员变量x赋值为100 ob.setX(200); /将成员变量x赋值为200 System.out.println( oa的成员变量 x= + oa.getX() ); System.out.println( ob的成员变量 x= + ob.getX() ); 程序中分别为两个对象oa和ob的成员变量赋了不同的值,然后再分别显示它们的值。程序的输出结果如下:oa的成员变量 x= 100ob的成员变量 x= 200这个结果完全在预料之中。但如果深入研究一下,还是会存在一些疑问:到底系统是如何来管理这些对象的?显然,不同对象的成员变量一定是单独存放的,那么当它们都调用setX()方法的时候,这个方法如何知道要为哪一个对象的成员变量x赋值?一种简单的解决办法,是让每个对象的成员方法也单独存放,并且和成员变量存放在一起,它只处理本对象的成员变量。但这种方法实在是太笨,因为为每个对象存储一套成员方法(而且这些方法的执行语句是完全一样的)需要大量的空间,完全不符合代码重用的原则。所以,所有对象共用一套成员方法显然要经济高效得多。但这样又会带来一个问题,就是这些方法怎样才能区分目前要处理的是哪一个对象的成员变量。解决的答案就是this关键字。系统会将this指向当前对象,然后作为参数传递给成员方法。在方法访问成员变量时,系统会自动为成员变量加上一个this作为前缀,这样就可以区分是哪个对象的成员变量。当然,程序员也可以显式地加上this做前缀。比如,onlyTest类与下面这种形式等价:public class onlyTest private int x = 0; /设置成员变量x的值 public void setX(int ix) this.x = ix; /显式地加上this,表示本对象的变量x /获取成员变量x的值 public int getX() return this.x; 对于方法:public void setX(int ix)系统会自动加上形参this,如下:public void setX(onlyTest this, int ix)当通过“oa.setX(100)”来调用方法时,系统生成的是“oa.setX(oa,100)”,这样就很好地解决了区分各个对象成员的问题。3.6 构 造方 法构造方法是类中一种特殊的方法,它一般由系统在创建对象(即类实例化)时自动调用。构造方法是对象中第一个被执行的方法,主要用于申请内存、对类的成员变量进行初始化等操作。构造方法虽然也位于类里面,但在很多情况下与普通成员方法表现不同,所以也有人认为它不是成员方法,而且将其称为“构造器”。本书仍然沿用通常的称呼,将其称为构造方法。构造方法的一般形式为:构造方法名(参数列表) this(参数列表); |super(参数列表); 语句序列其中,this是调用其他的构造方法,super是调用父类的构造方法。它们都必须放在其他语句的前面。编写式构造方法要注意以下几点: 构造方法的名字必须和类的名字完全相同。 除了访问权修饰符之外,不能有其他任何修饰符,也就不能有返回值。 尽管没有返回值,但并不能用“void”修饰。 构造方法不能用static和final来修饰。一般也不用private修饰,这会导致无法在外部创建对象。 构造方法不能由对象显式地调用。一般通过new关键字来调用,或者用this、super来调用。 构造方法的参数列表可以为空,也可以有参数。根据参数的有无,可以将构造方法分为无参数的构造方法和带参数的构造方法。 用户定义的类可以拥有多个构造方法,但要求参数列表不同。 如果用户定义的类未提供任何构造方法时,系统会自动为其提供一个无参数的构造方法。3.6.1 无参数构造方法的定义和使用定义一个无参数的构造方法,从语法上来讲很简单,请看下面的示例。【例3.20】 无参数的构造方法示例。/-文件名constructNoPara.java,程序编号3.31-public class constructNoPara private int x = 0; /定义一个无参数的构造方法,它必须和类同名 public constructNoPara() System.out.println(这是无参数的构造方法); x = 100; /为成员变量赋值 /获取成员变量x的值 public int getX() return x; public static void main(String args) constructNoPara oa = new constructNoPara(); /隐式调用无参数的构造方法 System.out.println(x = + oa.getX() ); /输出成员变量x的值 调用构造方法使用的是“new constructNoPara()”,这是一种隐式的调用方法,不能写成“oa.constructNoPara()”的形式。注意到成员变量x,它在定义的时候已经赋了初值。在构造方法中,先是输出一条信息,然后再次为x赋值。由于构造方法的执行在定义成员变量之后,它会覆盖掉原来x的初值,所以x的值为100。程序的输出结果如下:这是无参数的构造方法x = 100对于初学者而言,最容易犯的错误是在构造方法之前加上“void”,变成下面这个 样子:public class constructNoPara private int x = 0; /试图定义一个无参数的构造方法 public void constructNoPara() /这里加了一个void System.out.println(这是无参数的构造方法); x = 100; /为成员变量赋值 /获取成员变量x的值 public int getX() return x; public static void main(String args) constructNoPara oa = new constructNoPara(); /隐式调用无参数的构造方法 System.out.println(x = + oa.getX() ); /输出成员变量x的值 这个程序仍然可以通过编译,但运行结果可能会出人意料。它的输出结果如下:x = 0这表明,程序员自己定义的无参数的构造方法根本就没有执行。这是因为加上“void”修饰符之后,constructNoPara()不再是一个构造方法,而成了一个普通方法。语句“constructNoPara oa = new constructNoPara();”并不是调用程序员自己定义的“构造方法”,而是调用了系统提供的默认的无参数的构造方法,这个方法其实什么事情也没做,自然也就不会更改x的值。%说明:C+程序员不会犯此类错误。因为在C+中,如果在构造方法前面加上void,编译器将报错。%注意:构造方法前的访问权限修饰符同样有4种,但通常不会是private类型。因为用它来修饰的话,无法在外部使用该构造方法。3.6.2 带参数构造方法的定义和使用在很多时候,需要根据不同的情况为成员变量赋不同的初值,这就需要传递参数给构造方法。因此,Java中允许定义带参数的构造方法,而且这种带参数的构造方法还可以定义多个(前提是参数列表有区别)这种现象被称为构造方法的重载。Java规定,如果程序员一个构造方法都不定义,那么系统会自动为其加上一个不带参数的构造方法。如果程序员至少定义了一个构造方法,那么系统不会再提供不带参数的构造方法。当用new来创建对象时,需要提供类型相容的参数,否则编译器将报错。【例3.21】 带参数的构造方法示例。/-文件名constructWithPara.java,程序编号3.32-public class constructWithPara private int x = 0; /定义一个带参数的构造方法 public constructWithPara(int ix) System.out.println(这是带参数的构造方法); x = ix; /为成员变量赋值 /获取成员变量x的值 public int getX() return x; public static void main(String args) constructWithPara oa = new constructWithPara(100); /隐式调用带参数的 构造方法 System.out.println(x = + oa.getX() ); 这个程序的流程和程序3.31完全一样,只是其中的构造方法多了一个参数而已。程序运行的结果如下:这是带参数的构造方法x = 100这个程序从表面上看没有什么问题,但实际上它存在着一个很大的隐患。如果将类constructWithPara提供给其他的程序员使用,使用者很有可能会按照一般的习惯这么来创建一个对象:constructWithPara oa = new constructWithPara();试图使用x的默认值。但这样是无法通过编译的,因为系统不会再为constructWithPara类提供无参数的构造方法。当此类被其他类继承时,这一问题显得越发严重,它甚至会导致根本无法写出一个子类。因此,强烈建议程序员在定义带参数的构造方法时,也要定义一个不带参数的构造方法,即便这个方法什么事情也不做。所以程序3.32应该改成下面这个样子:/-文件名constructWithPara.java,程序编号3.33-public class constructWithPara private int x = 0; /定义一个带参数的构造方法 public constructWithPara(int ix) System.out.println(这是带参数的构造方法); x = ix; /为成员变量赋值 /定义一个不带参数的构造方法 public constructWithPara() /获取成员变量x的值 public int getX() return x; public static void main(String args) constructWithPara oa = new constructWithPara(100); /隐式调用带参数的 构造方法 System.out.println(x = + oa.getX() ); 3.6.3 this关键字和构造方法的调用在3.5.3节中,已经介绍了this关键字的作用作为隐含参数指向本对象。其实this关键字还有一个作用,就是用来显示地调用构造方法。它的使用格式如下:this(参数列表)系统将根据参数列表来决定调用哪一个构造方法。使用this时还需注意下面几点: 用this调用构造方法时,该语句只能用在构造方法中。 this语句必须是构造方法中的第一条语句。 和new不同,this虽然可以调用构造方法,但它只是执行构造方法中的语句,并不会创建对象。【例3.22】 用this调用构造方法示例。这里仍然使用程序3.33,并在无参数的构造方法中加上this语句来为x赋初值。/-文件名constructWithPara.java,程序编号3.34-public class constructWithPara private int x = 0; /定义一个带参数的构造方法 public constructWithPara(int ix) System.out.println(这是带参数的构造方法); x = ix; /为成员变量赋值 /定义一个不带参数的构造方法 public constructWithPara() this(100); /调用带参数的构造方法为x赋值 System.out.println(这是无参数的构造方法); /获取成员变量x的值 public int getX() return x; public static void main(String args) constructWithPara oa = new constructWithPara(); /隐式调用无参数的构造方法 System.out.println(x = + oa.getX() ); 在main()方法中利用无参数的构造方法来创建对象,而在无参数的构造方法中,用this来调用带参数的构造方法,然后再输出一条信息。程序输出结果如下:这是带参数的构造方法这是无参数的构造方法x = 100在constructWithPara()方法中,特别注意不要写成下面这个样子:public constructWithPara() System.out.println(这是无参数的构造方法); this(100); /调用带参数的构造方法为x赋值这样编译会出错,因为this调用构造方法只能作为第一条语句。读者可能会觉得程序3.34用this调用另外一个构造方法为x赋值过于麻烦,不如直接为x赋值更简单。当然,这只是一个示例程序,这么做的原因在于:很多情况下,多个构造方法可能会做相同的事情,只是参数有点区别,这就可以将这段相同的代码单独抽取出来成为一个构造方法,然后使用this来调用它3.7 静 态 方 法前面已经介绍过,成员变量分为实例变量和静态变量。其中实例变量属于某一个具体的实例,必须在类实例化后才真正存在,不同的对象拥有不同的实例变量。而静态变量被该类所有的对象公有(相当于全局变量),不需要实例化就已经存在。方法也可分为实例方法和静态方法。其中,实例方法必须在类实例化之后通过对象来调用,而静态方法可以在类实例化之前就使用。与成员变量不同的是:无论哪种方法,在内存中只有一份无论该类有多少个实例,都共用同一个方法。本节以前的例子中,除了main()方法,其余的方法都是实例方法,而main()则是一个静态方法,所以它才能够被系统直接调用。3.7.1 静态方法的声明和定义定义一个静态方法和定义一个实例方法,在形式上并没有什么区别,只是在声明的头部,需要加上一个关键字static。它的一般语法形式如下:访问权限修饰符 static 返回值类型 方法名(参数列表) 语句序列例如下面是一个静态的方法:public static void stFun() System.out.println(这是一个静态方法);3.7.2 静态方法和实例方法的区别静态方法和实例方法的区别主要体现在两个方面: 在外部调用静态方法时,可以使用“类名.方法名”的方式,也可以使用“对象名.方法名”的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。 静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制。下面几个例子展示了这一区别。【例3.23】 调用静态方法示例。/-文件名hasStaticMethod.java,程序编号3.35-public class hasStaticMethod /定义一个静态方法 public static void callMe() System.out.println(This is a static method.); 下面这个程序使用两种形式来调用静态方法。/-文件名invokeStaticMethod.java,程序编号3.36-public class invokeStaticMethod public static void main(String args) hasStaticMethod.callMe(); /不创建对象,直接调用静态方法 hasStaticMethod oa = new hasStaticMethod(); /创建一个对象 oa.callMe(); /利用对象来调用静态方法 程序3.36两次调用静态方法,都是允许的,程序的输出如下:This is a static method.This is a static method.允许不创建对象而调用静态方法,是Java为了减少程序员调用某些常用方法时的麻烦,而允许程序员按照传统的C语言中使用函数的方式来使用方法。典型的例子是前面某些程序中使用“Math.ramdon()”来获取随机数。【例3.24】 静态方法访问成员变量示例。/-文件名accessMember.java,程序编号3.37-class accessMember private static int sa; /定义一个静态成员变量 private int ia; /定义一个实例成员变量 /下面定义一个静态方法 static void statMethod() int i = 0; /正确,可以有自己的局部变量 sa = 10; /正确,静态方法可以使用静态变量 otherStat(); /正确,可以调用静态方法 ia = 20; /错误,不能使用实例变量 insMethod(); /错误,不能调用实例方法 static void otherStat() /下面定义一个实例方法 void insMethod() int i = 0; /正确,可以有自己的局部变量 sa = 15; /正确,可以使用静态变量 ia = 30; /正确,可以使用实例变量 statMethod(); /正确,可以调用静态方法 本例其实可以概括成一句话:静态方法只能访问静态成员,实例方法可以访问静态和实例成员。之所以不允许静态方法访问实例成员变量,是因为实例成员变量是属于某个对象的,而静态方法在执行时,并不一定存在对象。同样,因为实例方法可以访问实例成员变量,如果允许静态方法调用实例方法,将间接地允许它使用实例成员变量,所以它也不能调用实例方法。基于同样的道理,静态方法中也不能使用关键字this。main()方法是一个典型的静态方法,它同样遵循一般静态方法的规则,所以它可以由系统在创建对象之前就调用。下面这个程序有个错误,请读者仔细查看。public class hasErrorint insVar = 100; public static void main(String args) System.out.println(insVar = + insVar); 3.7.3 静态代码块在类中,可以将某一块代码声明为静态的,这样的程序块叫静态初始化段。静态代码块的一般形式如下:static 语句序列 静态代码块只能定义在类里面,它独立于任何方法,不能定义在方法里面。 静态代码块里面的变量都是局部变量,只在本块内有效。 静态代码块会在类被加载时自动执行,而无论加载者是JVM还是其他的类。 一个类中允许定义多个静态代码块,执行的顺序根据定义的顺序进行。 静态代码块只能访问类的静态成员,而不允许访问实例成员。【例3.25】 静态代码块运行示例1。/-文件名staticBlock.java,程序编号3.38-public class staticBlock /定义一个普通的main()方法 public static void main(String args) System.out.println(This is main method.); /定义一个静态代码块 static System.out.println(This is static block.); int stVar = 0; /这是一个局部变量,只在本块内有效 编译通过后,用java命令加载本程序,会得到如下输出:This is static block.This is main method.从以上输出结果中可以看出,静态代码块甚至在main方法之前就被执行。在main()方法中可以完成的任务在静态代码块中都可以完成。但是二者在执行上仍然有一些区别,请看下例。【例3.26】 静态代码块和main()方法的区别。这里仍然使用例3.25中的staticBlock类,然后新定义一个类来使用它。/-文件名useStaticBlock.java,程序编号3.39-public class useStaticBolck public static void main(String args) new staticBlock(); /创建一个staticBlock的对象 本程序没有像以前的程序那样,在创建对象时使用一个变量来接收对象,因为这个程序在后面并不需要用到这个变量。程序的输出如下:This is static block.这一次,只执行了静态代码块,main()方法在这种情况下是不会被执行的。最后来写一个复杂一点的静态代码块的例子,它综合体现了静态代码块的使用方法,请读者注意注释说明。【例3.27】 静态代码块使用示例2。/-文件名staticBlock.java,程序编号3.40-public class staticBlock static int stMember = 100; /定义静态成员变量 public static void main(String args) System.out.println(This is main method.); /第一个静态代码块 static System.out
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025福建厦门市海水养殖生物育种全国重点实验室(第一批)招聘考前自测高频考点模拟试题附答案详解(典型题)
- 2025中心医院正畸新技术应用考核
- 2025年宿州市宿马园区两站两员招聘11人模拟试卷及答案详解参考
- 2025儿童医院重症论文撰写考核
- 2025第二人民医院时间窗边缘患者溶栓考核
- 2025中心医院血管炎相关抗体检测解读考核
- 大学蒹葭课件
- 2025北京化工大学化办公室(中心)招聘1人模拟试卷及答案详解(考点梳理)
- 张家口市人民医院超声诊断质量控制考核
- 秦皇岛市中医院病案安全防护考核
- 2025年全国青少年禁毒知识竞赛小学组题库(附答案)
- 聚会饮酒安全教育培训课件
- 2025年CCAA服务认证基础考试试题(答案+解析)
- 2025年辅警招聘考试试题库附答案(能力提升)
- 临床医学职业生涯规划
- 钢结构大棚承揽合同范本
- 2025至2030年中国液态锂电池行业市场发展现状及投资潜力预测报告
- 机房设备维修服务项目投标方案(技术标)
- 食品安全法规试题及答案
- (2025年标准)个人薪酬协议书
- 搅拌车司机安全培训课件
评论
0/150
提交评论