鸿 网 互 联 www.68idc.cn

当前位置 : 服务器租用 > 编程语言开发 > erlang > >

Java的修饰符

来源:互联网 作者:佚名 时间:2016-07-17 21:12
像其他语言一样,Java可以使用修饰符来修饰类中方法和属性。主要有两类修饰符: 访问修饰符:default, public , protected, private 非访问修饰符:final, abstract, strictfp 修饰符一般使用在一个语句的前端,例: public void Pig{ int a = 1; protected

像其他语言一样,Java可以使用修饰符来修饰类中方法和属性。主要有两类修饰符:

访问修饰符:default, public , protected, private

非访问修饰符:final, abstract, strictfp

修饰符一般使用在一个语句的前端,例:

public void Pig{
   int a = 1;
   protected String b = "b"; 
   private static final int c = 1;
   
 }



Java中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。Java支持4种不同的访问权限。

默认的,也称为 default,在同一包内可见,不使用任何修饰符。

私有的,以 private 修饰符指定,在同一类内可见。

共有的,以 public 修饰符指定,对所有类可见。

受保护的,以 protected 修饰符指定,对同一包内的类和所有子类可见。

默认访问修饰符-不使用任何关键字

使用默认访问修饰符声明的变量和方法,对同一个包内的类是可见的。接口里的变量都隐式声明为public static final,而接口里的方法默认情况下访问权限为public。

私有访问修饰符-private

私有访问修饰符是最严格的访问级别,所以被声明为private的方法、变量和构造方法只能被所属类访问,并且类和接口不能声明为private。

public class Pig{

   private int num = 1;
   public int getNum(){
	return num;
   }
   public void setNum(int num){
	this.num = num;
   }
}
 

公有访问修饰符-public

被声明为public的类、方法、构造方法和接口能够被任何其他类访问。

如果几个相互访问的public类分布在不同的包中,则需要导入相应public类所在的包。由于类的继承性,类所有的公有方法和变量都能被其子类继承。


受保护的访问修饰符-protected

被声明为protected的变量、方法和构造器能被同一个包中的任何其他类访问,也能够被不同包中的子类访问。

Protected访问修饰符不能修饰类和接口,方法和成员变量能够声明为protected,但是接口的成员变量和成员方法不能声明为protected。

子类能访问Protected修饰符声明的方法和变量,这样就能保护不相关的类使用这些方法和变量。

访问控制和继承

请注意以下方法继承的规则:

  • 父类中声明为public的方法在子类中也必须为public。

  • 父类中声明为protected的方法在子类中要么声明为protected,要么声明为public。不能声明为private。

  • 父类中声明为private的方法,不能够被继承。

非访问修饰符

为了实现一些其他的功能,Java也提供了许多非访问修饰符。

static修饰符,用来创建类方法和类变量。

Final修饰符,用来修饰类、方法和变量,final修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的

Abstract修饰符,用来创建抽象类和抽象方法

Synchronized和volatile修饰符,主要用于线程的编程。

Static修饰符

  • 静态变量:

    Static关键字用来声明独立于对象的静态变量,无论一个类实例化多少对象,它的静态变量只有一份拷贝。 静态变量也被成为类变量。局部变量不能被声明为static变量。

     静态方法:

  • Static关键字用来声明独立于对象的静态方法。静态方法不能使用类的非静态变量。静态方法从参数列表得到数据,然后计算这些数据。(这就是访问权限的问题了)。

         被static 修饰符修饰的成员方法和成员变量是独立于该类的任何对象的,可以被所有的类所共享。应为在加载(还没有实例化该类之前),JVM就已经为静态方法和静态变量分配内存空间。到时候只要使用类名去访问就可以了。被public 修饰的static成员变量和成员方法本质是全局变量或者是全局方法。任何一个类都可以同个类名访问内部和成员变量和成员方法

  • static代码块

      也叫做静态代码块,独立于类成员的代码块。在一个类中可以有多个静态代码块,位置可以任意,它不再任何方法体内,JVM加载类的时候,会自动执行静态代码块(记住:在加载类的时候就已经执行了,不用等待实例化类)。如果是由对各静态代码块,那么JVM就会按照这些静态代码块出现的顺序执行它们。每个静态代码块自会执行一次。(就是这个程序从开始运行到结束只会执行一次)。

public class HellowJava {

static{}
 public static void main(String[] arguments) {
		System.out.println("main程序");
		new StaticTest();
		
	}

}

class StaticTest{
	
	public StaticTest(){
		System.out.println("StaticTest");
	}
	static{
		System.out.println("静态代码块0");
	}
	static{
		System.out.println("静态代码块1");
	}
	
}

执行结果:

main静态代码块
main程序
静态代码块0
静态代码块1
StaticTest


解释:程序执行后,先加载 HellowJava 类 ,这时候执行这个类中的静态代码块,加载完毕那个后直接执行 mian() 方法,

  按顺序先执行 System.out.println("main程序");

  再加载StaticTest 类,这时候执行StaticTest中的静态代码块,并且按顺序执行这些代码块

 最后实例化这个StaticTest类(这时候就会调用构造方法)


public class HellowJava {

    static{
        System.out.println("main静态代码块");
    }
    public static void main(String[] arguments) {
        System.out.println("main程序"<span style="color:#FF0000;">+StaticTest.a)</span>;  //这里的就造成了 StaticTest 类的加载(就是静态代码块会执行)<pre name="code" class="html">StaticTest
new StaticTest(); }}
class StaticTest{
public StaticTest(){
System.out.println("StaticTest"); }
static{ a=1; System.out.println("静态代码块0"); }
static{ System.out.println("静态代码块1"); }
public static final int a ;
}

结果:

main静态代码块静态代码块0静态代码块1main程序1   StaticTest解释:本来以为static 修饰的代码都是会按顺序直接执行或者分配内存的。看来好像不是这样子。怎么说呢。从最后一行代码可以看到我把静态变量的定义放在了最后面,但是并没有出现任何报错,说明了JVM记载的时候是首先加载静态变量,再加载静态代码块的。(个人理解,喜欢就喷吧)

static和final一块用表示什么

static final用来修饰成员变量和成员方法,可以理解为“全局常量”。

   对于变量 :表示一旦给定值就不可以更改,并且可以通过类名来访问。

  对于方法: 表示不可以覆盖,并且可以通过类名来访问。

声明静态方法的限制:

 仅能调用其他的static方法;

仅能访问static 数据

不能以任何形式引用this 和super(和继承有关)

Final

Final方法

类中的Final方法可以被子类继承,但是不能被子类修改。

声明final方法的主要目的是防止该方法的内容被修改。

Final类

Final类不能被继承,没有类能够继承final类的任何特性。

Final修饰符

final变量能被显性的初始化,并且只可以初始化一次。被声明为final的对象不能指向不同的对象。但是final中的值是可以改变的。也就是说final中对象的引用不能够改变,但是里边的值可以改变。

例如: final Integer a =10;  Integer b =20;  可以这样改变  a =11;  或 a =20;  但是不可以  a =b ;

Final修饰符通常和static修饰符一起使用来创建类常量。

final修饰的成员变量
(1)final修饰的成员变量一旦赋值后,不能被重新赋值。
(2)final修饰的实例Field,要么在定义该Field的时候指定初始值,要么在普通初始化块或构造器中指定初始值。但是如果在普通初始化块中为某个实例Field指定了初始值,则不能再在构造器中指定初始值。
(3)final修饰的类Field,要么在定义该Field的时候指定初始值,要么在静态代码块中定义初始值。
(4)如果在构造器或初始化块中对final成员变量进行初始化,则不要在初始化之前就访问该成员的值。

class finalTest{
	
	final int a = 1;  //直接赋值
	final String b ;
	{
		b = "b";   //在代码块中赋值
		//这个代码块块只有当实例化这个类的时候优先于静态方法执行,
        //和构造方法无关,实例化的时候都会去执行 //比构造函数先执行
	}
	
	final boolean c;
	public finalTest(){   //在构造函数中赋值
		c = false;
	}
	
	final static int d = 8;        //直接赋值 
	
	final static int e;
	static{
		e = 1;     //在静态代码块中赋值
	}
	
}

final 的局部变量
(1)系统不会对局部变量进行初始化。布局变量必须要显示初始化。所以final修饰的局部变量既可以在定义的时候指定默认值,也可以不指定默认值。
(2)final修饰形参的时候,不能赋值

.final修饰基本数据类型变量和修饰引用类型变量的区别
final修饰基本数据类型的变量,一旦该变量赋值后,就不能被重新复制赋值了。
对于引用类型的变量,保存的只是引用,final修饰的应用类型的变量只是保证这个对象不改变,但是这个对象的内部内容是可以发生改变的。比如:
 
<span style="font-size:12px;">final  List<String> list = new ArrayList();
list.add("a"); list.add("b");
<span style="font-family:Verdana, Arial, Helvetica, sans-serif;">中</span></span>
这里可以看到list在被使用final修饰后还是可以往里边添加内容的,list的内部可以改变。
再看:
<span style="font-size:12px;">final int a = 1;
</span><span style="font-size:12px;">a =2;</span>
这个系统会报错。

final 的宏变量

(1)final 的一个重要的用途就是宏变量,当定义final变量是就制定了初值,这个初值是在编译的时候就加载进来了。编译会把程序中所用到的该变量的地方替换成该变量的值。

public class FinalTest {
    public static void main(String[] args){
        final String name = "小明" + 22.0;
        final String name1 = "小明" + String.valueOf(22.0);
        System.out.println(name == "小明22.0");
        System.out.println(name1 == "小明22.0");
    }
}
结果:

true
false


final String name1 = "小明"+String.valueOf(22.0); 中调用了String类的方法,所以在编译的时候无法确定name1的值,所以name1不会当作是宏变量。


package cn.lsl;

public class FinalTest {
    public static void main(String[] args){
        String s1 = "小明";
        String s2 = "小" + "明";
        System.out.println(s1 == s2);    //true
        
        String str1 = "小";
        String str2 = "明";
        String s3 = str1 + str2;
        System.out.println(s1 == s3);        //false
        
        //宏替换
        final String str3 = "小";
        final String str4 = "明";
        String s4 = str3 + str4;
        System.out.println(s1 == s4);        //true
    }
}

(1)Java会使用常量池管理直接使用过的字符串直接量。 String  a = "Hellow" ; 那么字符串池会缓存一个字符串 “Hellow”,当执行String b = "Hellow",会直接让b 指向“Hellow”  这个字符串, 所以a == b ;是true

(2)String s3 = str1+str2;在编译时没有办法确定s3的值。

(3)String s4 = str3+str4;应为执行了宏变换,所以在编译的时候就已经确定了s4的值


用final修饰的方法不能被重写。用final修饰的类不能有子类。

不可变类
不可变类是指创建该类的实例后,该实例的Field是不可改变的。
如果创建自定义的不可变类,应该遵循如下规则
(1)使用private和final修饰符来修饰该类的Field。
(2)提供带参数的构造器,用于传入参数来初始化类里的Field。
(3)仅为该类的Field提供getter方法,不要为该类的Field提供setter方法。
(4)如果有必要,重写Object类的hashCode和equals方法。


Abstract修饰符

抽象类:

abstract修饰符不能用来实例化对象,声明这个抽象类的唯一目的是为了将来对这个类进行扩充。

一个类不能同时被abstract和final修饰,如果这个类包含抽象方法,那么这个类一定要声明为抽象类,否则出现错误。

抽象类的内部可以包含抽象方法和非抽象方法。

抽象类如下:

abstract class CaraVan{
   private double price;
   private  String model ;
   private String year;
   public abstract void setName(String name);  //抽象方法
   public abstract String getName();
 }

抽象方法:

抽象方法是一种没有任何实现的方法,具体的实现依靠子类方法实现。该方法也不可以声明为final 和static

任何继承了抽象类的子类必须实现父类的中抽象方法,除非这个子类也是抽象类。

如果一个类中包含抽象方法,那么这个类必须是抽象类,一个抽象类中也可以不包含任何的抽象方法。

例:

abstract class Animal{
	public abstract void run(); //抽象方法。
	
}

 class Pig extends Animal{

	@Override
	public void run() {
		// TODO Auto-generated method stub
		//do ...
	}
	
}

和接口(Interface)的区别。

1、相同点:

(1)都是抽象类,都是不能实例化。

(2)interface实现类及abstact class 的之类都必须实现已经声明的抽象方法。

2、不同点

(1)interface 的实现使用的是implements ,而abstract class 的实现使用的是extends.

(2)一个类可以实现多个interface但是只可以继承一个abstract class

(3)interface强调功能的实现,而abstract 强调所属的关系。

(4)实现显示不一样,interface的每个方法都是抽象方法,没有方法体,而abstract class 子类可以选择的实现这些方法(其他的可以在abstract class类中直接实现方法体)。


抽象类的这个选择有两点含义:

      一是Abastract class中并非所有的方法都是抽象的,只有那些冠有abstract的方法才是抽象的,子类必须实现。那些没有abstract的方法,在Abstrct class中必须定义方法体。

      二是abstract class的子类在继承它时,对非抽象方法既可以直接继承,也可以覆盖;而对抽象方法,可以选择实现,也可以通过再次声明其方法为抽象的方式,无需实现,留给其子类来实现,但此类必须也声明为抽象类。既是抽象类,当然也不能实例化。

(5)interface是完全抽象的。只能声明方法,权限也只能声明为public,不能定义方法体,也不可以实例化变量(都是 public static fianl 类型)

详细参考:http://blog.csdn.net/zhandoushi1982/article/details/8458081


Synchronized修饰符

Synchronized关键字声明的方法同一时间只能被一个线程访问。Synchronized修饰符可以应用于四个访问修饰符。

实例:

public synchronized void setName(){
		//...
}

使用详情:

http://www.cnblogs.com/GnagWang/archive/2011/02/27/1966606.html

测试代码:




相关测试代码:

参考:http://blog.csdn.net/m13666368773/article/details/7513049

参考:http://www.runoob.com/java/java-modifier-types.html

参考:http://www.cnblogs.com/EvanLiu/archive/2013/06/13/3134776.html

参考:http://blog.csdn.net/zhandoushi1982/article/details/8458081





















网友评论
<