`

[转]构造函数为什么不能被abstract/static/final/native/stricftp/synchronized修饰 及 一些关键字的用法

    博客分类:
  • java
 
阅读更多

from:http://www.blogjava.net/realsmy/archive/2007/04/10/109256.html

from:http://www.wljcz.com/html/j2se/javajc/2010/0408/3262.html

from:http://www.javaeye.com/topic/72543

from:http://www.dingkao.com/a/100627/50164/

from:http://blog.pfan.cn/sword2008/13772.html

from:http://www.cnblogs.com/wjun530/archive/2007/09/15/893802.html

 

不同于方法,构造器不能是abstract, static, final, native, strictfp, 或者synchronized的.
1.构造器不是通过继承得到的,所以没有必要把它声明为final的。
2.同理,一个抽象的构造器将永远不会被实现。(所以也不能声明为abstract的)
3.构造器总是关联一个对象而被调用,所以把它声明为static是没有意义的。
4.没有实际的需要把构造器定义成同步的,因为它将会在构造的时候锁住该对象,直到所有的构造器完成它们的工作,这个构造的过程对其它线程来说,通常是不可访问的。 (synchronized)
5.本地化的方法情况特别复杂,所以JVM调用起来非常麻烦,需要考虑很多种情况,没有native关键字的情况下,JVM实现起来比较容易。

 

注:strictfp、native、transient、volatile用法

1)strictfp:strictfp的意思是FP-strict,也就是说精确浮点的意思。

在Java虚拟机进行浮点运算时,如果没有指定strictfp关键字时, Java的编译器以及运行环境在对浮点运算的表达式是采取一种近似于我行我素的行为来完成这些操作,以致于得到的结果往往无法令你满意。而一旦使用了 strictfp来声明一个类、接口或者方法时,那么所声明的范围内Java的编译器以及运行环境会完全依照浮点规范IEEE-754来执行。因此如果你想让你的浮点运算更加精确,而且不会因为不同的硬件平台所执行的结果不一致的话,那就请用关键字strictfp。

你可以将一个类、接口以及方法声明为strictfp,但是不允许对接口中的方法以及构造函数声明strictfp关键字。例如:

一、错误的使用方法

interface A {
    strictfp void f(); //接口中的方法
}
public class FpDemo2 {
    strictfp FpDemo2() {} // 构造函数
}

二、合法的使用关键字strictfp

strictfp interface A {} //接口
public strictfp class FpDemo1 { //类
    strictfp void f() {} //方法
}

2)native:native是方法修饰符。Native方法是由另外一种语言(如c/c++,FORTRAN,汇编)实现的本地方法。有时java应用需要与java外面的环境交互。这是本地方法存在的主要原因。

因为在外部实现了方法,所以在java代码中,就不需要声明了,有点类似于接口方法。Native可以和其他一些修饰符连用,但是abstract方法和Interface方法不能用native来修饰

在定义一个native method时,并不提供实现体(有些像定义一个java interface),因为其实现体是由非java语言在外面实现的。例:   
    public class IHaveNatives
    {
      native public void Native1( int x ) ;
      native static public long Native2() ;
      native synchronized private float Native3( Object o ) ;
      native void Native4( int[] ary ) throws Exception ;
    }
    这些方法的声明描述了一些非java代码在这些java代码里看起来像什么样子(view).
    不能用abstract的原因:这是合理的,因为native暗示这些方法是有实现体的,只不过这些实现体是非java的,但是abstract却显然的指明这些方法无实现体。

    native与其它java标识符连用时,其意义同非Native Method并无差别,比如native static表明这个方法可以在不产生类的实例时直接调用,这非常方便,比如当你想用一个native method去调用一个C的类库时。上面的第三个方法用到了native synchronized,JVM在进入这个方法的实现体之前会执行同步锁机制

3)transient:变量修饰符(只能修饰字段)。

标记为transient的变量,在对象存储时,这些变量状态不会被持久化。当对象序列化地保存在存储器上时,不希望有些字段数据被保存,为了保证安全性,可以把这些字段声明为transient。

4)volatile:volatile修饰变量。在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。

volatile与synchronized的区别:

1.volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取;synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
2.volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的
3.volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性
4.volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
5.volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化

5)static:

1>静态方法:通常,在一个类中定义一个方法为static,那就是说,用类名而无需本类的对象即可调用此方法。静态方法常常为应用程序中的其它类提供一些实用工具所用。

2>静态变量:静态变量与静态方法类似。所有此类实例共享此静态变量,也就是说在类装载时,只分配一块存储空间,所有此类的对象都可以操控此块存储空间,当然对于final则另当别论了。

3>static定义的变量会优先于任何其它非static变量,不论其出现的顺序如何。

在static{}内的代码,是用来进行显式的静态变量初始化,这段代码只会初始化一次,且在类被第一次装载时。在涉及到继承的时候,会先初始化父类的static变量,然后是子类的,依次类推。

4>通常一个普通类不允许声明为静态的,只有一个内部类才可以。这时这个声明为静态的内部类可以直接作为一个普通类来使用,而不需实例一个外部类。但是,不能从静态内部类的对象中访问非静态的外围类对象和方法(可访问外部静态的对象、方法)。例如:

public class StaticCls{
  public static void main(String[] args){
    OuterCls.InnerCls oi=new OuterCls.InnerCls();
  }
}
class OuterCls{
  public static class InnerCls{
    InnerCls(){
      System.out.println("InnerCls");
    }
   }
}

PS:非static内部类,初始化方法:

outerObject=new outerClass(Constructor Parameters);

outerClass.innerClass innerObject=outerObject.new InnerClass(Constructor Parameters);

注意在创建非静态内部类对象时,一定要先创建起相应的外部类对象。至于原因,非静态内部类对象有着指向其外部类对象的引用,一个内部类对象可以访问创建它的外部类对象的内容,甚至包括私有变量!

static与非static内部类区别:1、静态内部类没有了指向外部的引用。2、在任何非静态内部类中,都不能有静态数据,静态方法或者又一个静态内部类(内部类的嵌套可以不止一层)。不过静态内部类中却可以拥有这一切。

6)final

final变量:

在类中定义变量时,在其前面加上final关键字,那便是说,这个变量一旦被初始化便不可改变,这里不可改变的意思对基本类型来说是其值不可变,而对于对象变量来说其引用不可再变。

其初始化可以在两个地方,一是其定义处,也就是说在final变量定义时直接给其赋值,二是在构造函数中。这两个地方只能选其一,要么在定义时给值,要么在构造函数中给值,不能同时既在定义时给了值,又在构造函数中给另外的值。

还有一种用法是定义方法中的参数为final,对于基本类型的变量,这样做并没有什么实际意义,因为基本类型的变量在调用方法时是传值的,也就是说你可以在方法中更改这个参数变量而不会影响到调用语句,然而对于对象变量,却显得很实用,因为对象变量在传递时是传递其引用,这样你在方法中对对象变量的修改也会影响到调用语句中的对象变量,当你在方法中不需要改变作为参数的对象变量时,明确使用final进行声明,会防止你无意的修改而影响到调用方法

final方法:
将方法声明为final,那就说明你已经知道这个方法提供的功能已经满足你要求,不需要进行扩展,并且也不允许任何从此类继承的类来覆写这个方法,但是继承仍然可以继承这个方法,也就是说可以直接使用。编译器在遇到调用final方法时候会转入内嵌inline机制,它会使你在调用final方法时,直接将方法主体插入到调用处,而不是进行例行的方法调用,例如保存断点,压栈等,这样可能会使你的程序效率有所提高,然而当你的方法主体非常庞大时,或你在多处调用此方法,那么你的调用主体代码便会迅速膨胀,可能反而会影响效率,所以你要慎用final进行方法定义。


final类:
当你将final用于类身上时,你就需要仔细考虑,因为一个final类是无法被任何人继承的,那也就意味着此类在一个继承树中是一个叶子类,并且此类的设计已被认为很完美而不需要进行修改或扩展。对于final类中的成员,你可以定义其为final,也可以不是final。对于方法,由于所属类为final的关系,自然也就成了final型的。你也可以明确的给final类中的方法加上一个final,但这显然没有意义。

7)static和final一块用表示什么
static final用来修饰成员变量和成员方法,可简单理解为“全局常量”!
对于变量,表示一旦给值就不可修改,并且通过类名可以访问; 对于方法,表示不可覆盖,并且可以通过类名直接访问。

分享到:
评论

相关推荐

    深入理解java构造器机理

    构造器可以有任何访问修饰符,例如 public、protected、private 或者没有修饰符,但不能有 abstract、final、native、static 或者 synchronized 修饰符。构造器没有返回值,也不需要 void。最后,构造器的命名与类名...

    JAVA面向对象基础PPT教案学习.pptx

    * 方法修饰符:public、protected、private、static、final、abstract、native、synchronized * 方法返回类型:void、基本数据类型、引用类型 五、面向对象编程思想 * 面向对象的基本思想:从现实世界中客观存在的...

    01-Java语言基础(关键字)

    它也可以应用于方法,表示该方法不能被子类重写,或者应用于类,表示此类不能被继承。 6. `void`: 在方法定义中,`void`表示该方法不返回任何值。 7. `int`, `float`, `double`, `char`, `boolean`: 这些是Java的...

    JAVA关键字总结(整理后最全最详细)

    抽象类不能被实例化,只能作为其他类的基类。抽象方法没有具体的实现,必须在子类中被重写。如果一个类包含至少一个抽象方法,那么这个类必须声明为抽象类。例如: ```java public abstract class AbstractClass {...

    net学习笔记及其他代码应用

    答:构造器Constructor不能被继承,因此不能重写Overriding,但可以被重载Overloading。 42.是否可以继承String类? 答:String类是final类故不可以继承。 43.try {}里有一个return语句,那么紧跟在这个try后的...

    Java理论复习

    - 构造函数可以被标记为`static`、`final`、`synchronized`、`abstract`、`native`等修饰符,但通常构造函数不会带有这些修饰符,因为它们都有特定的意义和限制。 #### 3. `final`关键字 - **概述**:`final`...

    java中构造方法和方法全面解析.pdf

    构造方法可以拥有公共(public)、受保护(protected)、私有(private)或默认(包级私有)的访问修饰符,但不能包含抽象(abstract)、最终(final)、本地(native)、静态(static)或同步(synchronized)这些...

    电子教材:《Java语言程序设计-关键字》pdf版(高清晰)

    - 表示抽象类或抽象方法,抽象类不能被实例化,只能通过继承的方式实现其具体功能。 2. **assert** - 用于声明断言语句,主要用于调试目的,帮助开发者检查假设是否正确。 3. **boolean** - 数据类型关键字,...

    Java面试宝典2012最新版

    25. abstract方法不能是static、native或synchronized。 26. 内部类分为静态内部类和非静态内部类,它们在访问外部类成员时有不同的规则和限制。 27. 内部类可以引用包含类的成员,但要遵循相应的访问权限。 28. ...

    最的java关键字解释.doc

    对于方法,表示不能被重写;对于变量,表示赋值后不能再改变。 19. `finally`:在异常处理中,无论是否发生异常,`finally`块中的代码都会被执行。 20. `float`:基本数据类型之一,表示单精度浮点数。 21. `for`...

    JAVA关键字,很详细的总结。

    - **abstract**:用于声明抽象类和方法,表明该类或方法不完整,不能实例化,必须被子类覆盖或实现。 - **class**:声明一个类的关键字,它是Java程序的基本构建单元,用于定义对象的行为和状态。 - **extends**:...

    java笔试题java笔试题java笔试题

    - 抽象类(abstract class)可以有构造函数、字段、非抽象方法,可以包含具体实现,可以被实例化(除非所有方法都是抽象的)。 - 接口(interface)只能包含抽象方法和常量,不能有具体实现,不能实例化,用于定义...

    java 面试宝典

    - abstract方法不能是static,但可以是native和synchronized。 - 内部类可以访问包含类的成员,但有其特殊的访问规则。 - 匿名内部类可以实现接口或继承类,但不能有构造函数。 - String不是基本数据类型,但其行为...

    java程序员面试题及解答.pdf,这是一份不错的文件

    21. abstract, static, native, synchronized 结合:abstract 方法不能是 static 或 native,因为它们是声明方法的实现方式。abstract 也不能是 synchronized,因为抽象方法没有具体实现。 22. 接口继承接口,抽象...

    Java面试宝典8.pdf

    19. 不能将abstract方法声明为static或synchronized,但可以声明为native。 20. 内部类分为静态内部类和非静态内部类。静态内部类不需要外部类的实例即可创建,而非静态内部类需要依附于外部类的实例。内部类可以...

    【05-面向对象(下)】

    •当使用final修饰基本数据类型时,不能对其重新赋值,不能被改变。 •但对引用类型的变量而言,它仅仅保存的是一个引用,final只能保证他的地址不变,但不能保证对象,所以引用 类型完全可以改变他的对象。 ...

    java面试32变态题

    - 构造函数不能被重写(override),因为构造函数是特殊的方法,用于初始化对象,不存在继承关系下的重写概念。 - 但是,可以在子类中调用父类的构造函数,这被称为构造函数的重用(use)。 #### 十三、String是否...

    java关键字

    1. `abstract`: 用于定义抽象类或抽象方法,抽象类不能被实例化,抽象方法没有具体实现,需要在子类中完成。 2. `assert`: 用于断言某个条件是否满足,通常用于调试。如果断言失败,程序将抛出 `AssertionError`。 ...

    JAVA面试宝典

    5. abstract方法不能同时是static、native或synchronized,因为这些关键字与抽象方法的定义相冲突。 6. 内部类可以引用外部类的成员变量和方法。StaticNestedClass是静态内部类,与外部类的实例没有依赖关系;而...

    java面试宝典

    - 构造函数不能被重写,因为构造函数是在创建新对象时调用的,不存在继承关系。 20. **接口与抽象类的使用** - 抽象类可以包含方法的实现细节,而接口只定义行为,不提供实现。 - 掌握如何使用`implements`...

Global site tag (gtag.js) - Google Analytics