访问控制
2016-04-22 20:19
393 查看
访问控制(或隐藏具体实现)与“最初的实现不恰当”有关。-Java编程思想
在软件开发过程中,我们经常会发现以前实现的某段代码还有更好的方式或是更快的算法,这时我们需要对代码进行重构。如果代码封装得很好的话,那我们只需要修改实现的部分就好了,其他调用了这段代码的地方根本不需要进行修改。相反,如果我们写的类暴露了过多的实现细节或是接口定义得不合理,那就很难进行代码重构了(我们需要保证客户代码不会因为这些改动而受到影响,即使我们的客户代码就在同一个项目内,我们也要尽量缩小改动能影响的范围)。
所以在面向对象编程中,我们需要考虑的一个问题就是如何把变动的和不变的事物区分开来。Java所提供的访问控制就能达到这个目的,将不变的事物以接口的形式提供给客户程序使用,而变动的事物则控制在类、子类或是包的内部,这样就能使代码改动的影响范围也类、子类或包的内部而不会影响到客户程序。
在Java中提供了public、protected、private和默认四种访问控制。对于使用public的属性或方法,所有使用该类的代码都能访问该属性或方法,通常使用public定义需要暴露给客户端的接口或是一些全局的静态常量。
当属性或方法(包括内部类)不使用任何访问控制关键字时,该属性或方法就具有包访问控制权限。在该类所在包的内部使用这个类时,具有包访问权限的属性或方法是可见的,而在该类所在包的外部使用这个类时,具有包访问权限的属性或方法是不可见的。举例来说:
当属性或方法使用private关键字时,该属性或方法只能有该属性所在类自己访问,其他类都不能访问
当属性或方法使用protected关键字时,该属性或方法可以被该类所在包的其他类访问(也就是它具有包访问权限),与此同时,它也能被它的子类访问,而其他类不能访问,举例来说:
当属性是public时,所有类都可以访问
在软件开发过程中,我们经常会发现以前实现的某段代码还有更好的方式或是更快的算法,这时我们需要对代码进行重构。如果代码封装得很好的话,那我们只需要修改实现的部分就好了,其他调用了这段代码的地方根本不需要进行修改。相反,如果我们写的类暴露了过多的实现细节或是接口定义得不合理,那就很难进行代码重构了(我们需要保证客户代码不会因为这些改动而受到影响,即使我们的客户代码就在同一个项目内,我们也要尽量缩小改动能影响的范围)。
所以在面向对象编程中,我们需要考虑的一个问题就是如何把变动的和不变的事物区分开来。Java所提供的访问控制就能达到这个目的,将不变的事物以接口的形式提供给客户程序使用,而变动的事物则控制在类、子类或是包的内部,这样就能使代码改动的影响范围也类、子类或包的内部而不会影响到客户程序。
在Java中提供了public、protected、private和默认四种访问控制。对于使用public的属性或方法,所有使用该类的代码都能访问该属性或方法,通常使用public定义需要暴露给客户端的接口或是一些全局的静态常量。
当属性或方法(包括内部类)不使用任何访问控制关键字时,该属性或方法就具有包访问控制权限。在该类所在包的内部使用这个类时,具有包访问权限的属性或方法是可见的,而在该类所在包的外部使用这个类时,具有包访问权限的属性或方法是不可见的。举例来说:
package package1; public class Test1 { int field1; } package package1; public class Test2 { public void test(Test1 t) { int j = t.field1;//这里可以访问Test1的feild1属性,因为它具有包访问权限 } } package package2; import package1.Test1; public class Test { public void test(Test1 t) { //int k = t.field1;编译不通过,因为Test1的feild1具有包访问权限,在package2中不能访问 } }
当属性或方法使用private关键字时,该属性或方法只能有该属性所在类自己访问,其他类都不能访问
package package1; public class Test1 { private int field1; public void test() { int j = field1;//这里可以访问,因为test()和field1都在Test1里 } } package package1; public class Test2 { public void test(Test1 t) { int j = t.field1;//这里不能可以访问Test1的feild1属性,因为它是私有属性 } }
当属性或方法使用protected关键字时,该属性或方法可以被该类所在包的其他类访问(也就是它具有包访问权限),与此同时,它也能被它的子类访问,而其他类不能访问,举例来说:
package package1; public class Test1 { protected int field1; private int field2; public void test() { int j = field1;//这里可以访问,因为test()和field1都在Test1里 int i = t.field2;//这里可以访问feild2,因为test()和field2都在Test1里 } } package package1; public class Test2 { public void test(Test1 t) { int j = t.field1;//这里可以访问Test1的feild1属性,因为它具有包访问权限 //int i = t.field2;//这里不可以访问feild2,因为它是Test1的私有属性 } } package package2; import package1.Test1; public class Test extends Test1 { public void test2() { int j = field1;//这里可以访问,Test继承了Test1的所有属性和方法,并且Test1的field1是protected的,所以Test可以访问 //int i = t.field2;//这里不可以访问feild2,因为它是Test1的私有属性 } } package package2; import pacakage1.Test1; public class T { public void test2() { //int j = field1;这里不可以访问feild1,因为它是protected的,而T既不是Test1的子类,也不在package1(Test1所在包)内 //int i = t.field2;这里不可以访问feild2,因为它是Test1的私有属性 } }
当属性是public时,所有类都可以访问
package package1; public class Test1 { protected int field1; private int field2; public void test() { int j = field1; int i = t.field2; } } package package1; public class Test2 { public void test(Test1 t) { int j = t.field1; int i = t.field2; } } package package2; import package1.Test1; public class Test extends Test1 { public void test2() { int j = field1; int i = t.field2; } } package package2; import pacakage1.Test1; public class T { public void test2() { int j = field1; int i = t.field2; } }