关于Java中的访问控制与Static关键字
一、介绍
先来介绍一下Java中的几个访问关键字,在此之前先来看一个场景:
场景1:工程师A编写了一个类ClassA,但是工程师A并不希望ClassA被该应用中其他所用的类都访问到,那么该如何处理?
场景2:如果工程师A编写了一个类ClassA,其中有两个方法fun1、fun2,工程师只想让fun1对外可见,也就是说,如果别的工程师来调用ClassA,只可以调用方法fun1,那么该怎么处理?
此时,访问权限控制便可以起到作用了。
在Java中,提供了四种访问权限控制:默认访问权限(包访问权限),public,private以及protected。
注意,上述四种访问权限,只有默认访问权限和public能够用来修饰类。修饰类的变量和方法四种权限都可以。(本处所说的类针对的是外部类,不包括内部类)
下面就分别针对修饰类和修饰类的成员来讲述这四种访问权限控制。
二、修饰类
修饰类有两种情况:默认访问权限(包访问权限):表示该类的内容对同属于一个包里的对象都是可见的。
Public访问权限:表示该类对其他所有类都可见。 下面举例子说明一下它们之间的区别:
mian.java:
1 package com.ztc; 2 import com.other.ceshi;//报错 3 import com.other.Publicceshi; 4 public class mian1 { 5 public static void main(String[] args) { 6 Dog x = new Dog(); 7 x.x(); 8 } 9 }
Dog.java:
1 package com.ztc; 2 3 class Dog {//默认访问权限(包访问权限),和mian类在一个包下面 4 public void x(){ 5 System.out.println("Dog"); 6 } 7 }
ceshi.java:
1 package com.other; 2 3 class ceshi//默认访问权限,包访问权限,但和mian类不在一个包下面 4 { 5 public void x(){ 6 System.out.println("ceshi"); 7 } 8 9 }
Publicceshi.java:
1 package com.other; 2 3 public class Publicceshi {//公开访问权限,和main类不在一个包下面 4 5 }
可以看到mian包里在引用ceshi类的时候会报错:

而其他类都可以正常引用,这就印证了上面所介绍的特点,如果想要引用不同包下的类,就必须使那个类的访问权限为Public。
三、修饰方法和变量
修饰方法和变量的访问修饰符有四种:
- 默认访问权限:如果一个类的方法和变量访问权限说默认的,说明在同一个包下的其他类能访问该方法或变量,而不同包下的类是不能去访问的
- Public:被Public修饰的方法或变量,在任何地方都是可见的
- Private:如果一个类方法或变量被Private修饰,那它在此类以外的地方都是不可见的,只允许在此类里进行访问
- Protect:如果一个类方法和变量被Protect修饰,那它对于同一个包下的类来说都是可见的,而对于不同包的类,只有继承了该类才能访问Protect修饰的方法和变量
具体的例子就不列举了,与上文所差不多的道理,而这里要介绍两点:
1、对于一个.class文件,如果存在Public修饰的类,那只能有一个这样修饰的类,并且类的名字一定要与Public类的名字一样,不然会报错
2、控制成员访问权限的意义在于:使用户不要接触到那些他们不该接触到的部分;让类库工作者能放心修改他们需要修改的地方,而不会对客户端产生重大影响
四、Static关键字
一般来说,当我们创建对象的时候,具体实现类才会被分配堆空间,而当我们不想创建对象,也就是省去new的过程就想调用方法或者使用变量时,就可以利用Static关键字,而这同样与 new一个对象的初始化过程有关:这一点可以看我的另一篇文章:https://www.cnblogs.com/kxxiaomutou/p/15599901.html,这里我们主要介绍关键词Static的用处。
在《Java编程思想》29页中有一句话:“当一个事物声明是Static时,就意味着这个域或方法不会与它的那个类的任何对象实例关联起来”,也就是说即使从未创建某个类的对象,,也可以调用其Static方法或访问其Static域。
只要类加载了,我们就可以通过类名去访问其中的Static(静态)方法或变量,这种特性可以用来优化程序的性能,下面将从静态方法、静态变量、静态代码块三个方面介绍:
1、静态方法
对于被Static修饰的方法来说,一般称其为静态方法,而上文说到静态方法已经与对象没有任何关系了,因此它也失去了与对象相关的东西,静态方法没有this关键字,它不能访问类中的非静态方法或者非静态变量,因为非静态方法必须依靠实例化后才能访问,而反过来倒是可行的,类中的其他方法是可以访问静态方法的,因为其不依靠任何对象,举个简单的例子:
1 public class Publicceshi { 2 static String x = "Staticx"; 3 String y = "y"; 4 public void print(){ 5 System.out.println(x); 6 System.out.println(y); 7 } 8 static public void print1(){ 9 System.out.println(x); 10 System.out.println(y);//报错 11 } 12 }
可以看到在静态方法里调用非静态的变量y出现了错误,这里我们假设如果可以调用,现在mian方法里有一句:Publicceshi.print2(),这样肯定会出现错误,因为此时的y变量都还没有,因为y的创建是需要对象的支撑,所以这样的写法肯定是错误的,这就是静态方法里只能调用静态方法或者变量的原因。
最常见的静态方法就是main方法,因为编译器在执行mian方法时没有创建任何对象,所以main方法必须是静态的,通过类名即可访问。
构造器是否为静态方法可以参考这篇文章:https://blog.csdn.net/qq_17864929/article/details/48006835
2、静态变量
static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
static成员变量的初始化顺序按照定义的顺序进行初始化。
3、静态代码块
static关键字还有一个重要的用处,就是修饰代码块,static代码块能放在类的任何位置,同时一个类也能拥有多个静态代码块,这些代码块统一在类加载的时候被执行,并且只会执行一次。static代码块可以用来优化代码的性能,至于怎么优化性能,可以看下面这个例子:
1 class Person{ 2 private Date birthDate; 3 4 public Person(Date birthDate) { 5 this.birthDate = birthDate; 6 } 7 8 boolean isBornBoomer() { 9 Date startDate = Date.valueOf("1946"); 10 Date endDate = Date.valueOf("1964"); 11 return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) < 0; 12 } 13 }
isBornBoomer是用来这个人是否是1946-1964年出生的,而每次isBornBoomer被调用的时候,都会生成startDate和birthDate两个对象,造成了空间浪费,如果改成这样效率会更好
1 class Person{ 2 private Date birthDate; 3 private static Date startDate,endDate; 4 static{ 5 startDate = Date.valueOf("1946"); 6 endDate = Date.valueOf("1964"); 7 } 8 9 public Person(Date birthDate) { 10 this.birthDate = birthDate; 11 } 12 13 boolean isBornBoomer() { 14 return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) < 0; 15
这样在类加载的时候statDate和endDate就被赋予好值了,不用每次都创建
4、static会改变类或者变量的访问权限吗?
答案是不会,在C++中的特性放在Java中是不合理的,Java中的访问权限只由Public、Protect、Private这几个关键字控制
5、能通过this来访问静态成员变量吗?
对于静态方法来说没有this,那非静态方法能通过this来调用静态成员变量吗?可以先看个例子,这段代码的输出是什么?
1 public class Main { 2 static int value = 33; 3 4 public static void main(String[] args) throws Exception{ 5 new Main().printValue(); 6 } 7 8 private void printValue(){ 9 int value = 3; 10 System.out.println(this.value); 11 } 12 }
33
这里面主要考察队this和static的理解。this代表什么?this代表当前对象,那么通过new Main()来调用printValue的话,当前对象就是通过new Main()生成的对象。而static变量是被对象所享有的,因此在printValue中的this.value的值毫无疑问是33。在printValue方法内部的value是局部变量,根本不可能与this关联,所以输出结果是33。在这里永远要记住一点:静态成员变量虽然独立于对象,但是不代表不可以通过对象去访问,所有的静态方法和静态变量都可以通过对象访问(只要访问权限足够)
5、局部变量能被static修饰吗
答案是不能,这是java的规定,至于为什么不能访问可以看这篇文章:
http://www.debugease.com/j2se/178932.html

浙公网安备 33010602011771号