java基础——访问控制符、修饰符及其他关键字

访问控制符的作用是说明被声明的内容(类、属性、方法和构造方法)的访问权限,就像发布的文件一样,在文件中标注机密,就是说明该文件可以被那些人阅读。
访问控制在面向对象技术中处于很重要的地位,合理的使用访问控制符,可以通过降低类和类之间的耦合性(关联性)来降低整个项目的复杂度,也便于整个项目的开发和维护。具体的实现就是通过访问控制符将类中会被其它类调用的内容开放出来,而把不希望别人调用的内容隐藏起来,这样一个类开放的信息变得比较有限,从而降低了整个项目开放的信息,另外因为不被别人调用的功能被隐藏起来,在修改类内部隐藏的内容时,只要最终的功能没有改变,即使改变功能的实现方式,项目中其它的类不需要更改,这样可以提高了代码的可维护性,便于项目代码的修改。
在Java 语言中访问控制权限有4 种,使用三个关键字进行表达,依次如下:
图片 
其中无访问控制符是指不书写任何的关键字,也代表一种访问权限,访问控制符的使用示例如下所示:
public class AccessControl {
        int n;
        public AccessControl(){
                init();
        }
        private void init(){}
                protected void test(int k){}
        } 
该示例代码中演示了各个访问控制符的实际使用示例,其中属性n 的访问控制符就是默认的。在实际使用时,类声明的访问控制符只有2 个:public 和无访问控制符,属性声明、构造方法声明和方法声明的访问控制符可以是以上4 种中的任何一个。
说明:
在4 种访问控制中:
public 一般称作公共权限,其限制最小,也可以说没有限制,使用public 修饰的内容可以在其它所有位置访问,只要能访问到对应的类,就可以访问到类内部public 修饰的内容,一般在项目中开放的方法和构造方法使用public 修饰,开放给项目使用的类也使用public 修饰。
protected 一般称作继承权限,使用protected 修饰的内容可以被同一个包中的类访问也可以在不同包内部的子类中访问,一般用于修饰只开放给子类的属性、方法和构造方法。无访问控制符一般称作包权限,无访问控制符修饰的内容可以被同一个包中的类访问,一般用于修饰项目中一个包内部的功能类,这些类的功能只是辅助其它的类实现,而为包外部的类提供功能。
private 一般称作私有权限,其限制最大,类似于文件中的绝密,使用private 修饰的内容只能在当前类中访问,而不能被类外部的任何内容访问,一般修饰不开放给外部使用的内容,修改private 的内容一般对外部的实现没有影响。
下面以两个基本的示例来说明访问控制符在实际项目中的使用方式。
第一个使用示例:在项目中,一般不会将类的属性开放给其它的类,也就是不允许外部的类直接访问属性,而是使用对应的存取方法来进行访问。例如在学校的学员管理系统中,需要实现的学生类,按照访问控制符的一般使用规则。
实现的代码如下:
/**
* 学员类,演示访问控制符的使用
*/
public class Student {
        /**年龄*/
        private int age;
        /**学员ID*/
        private int id;
        public int getAge() {
                return age;
        }
        public void setAge(int age) {
                if(age < 0){
                //处理代码,未实现
                }
                this.age = age;
                }
        public int getId() {
                return id;
        }
        public void setId(int id) {
                //校验id 是否合法的代码,未实现
                this.id = id;
        }
}

通过将属性的访问权限设定为private,限制所有类外部对属性的访问,而为了让外部可以访问这些属性,专门声明对应的get/set 方法来读取/存储数据,这样在设置属性值的set 方法中,可以对于参数做出基本的校验,在上面的示例代码中,留出了校验参数的位置,具体的代码未在示例代码中实现。
小技巧:在eclipse 中,get 和set 方法可以在选中对应类的代码以后,使用“Source”菜单中的“Generate Getters and Setters…”菜单实现。
第二个使用示例:在项目中,一般为了设计的需要实现一些特定的功能,下面介绍一下使用访问控制符实现的一个功能——使一个类既不能创建对象也不能被继承。实现的方法如下:该类中只实现一个构造方法,而且将该构造方法的访问权限设置为私有的。
具体实现代码如下:
/**
* 不能创建对象且不能被继承的子类
*/
public class PrivateDemo {
        private PrivateDemo(){}
}

在该示例中,PrivateDemo 类只有一个构造方法,且该构造方法为私有。按照以前的介绍,创建对象时需要调用构造方法,而private 修饰的构造方法无法在类的外部进行访问,所以无法创建对象。另外,在子类的构造方法中也需要调用父类的构造方法,由于private 的构造方法无法得到调用,所以该类也不可以有对应的子类。这里说明的只是两个基本的用途,在实际的项目中,可以根据需要灵
活的使用访问控制符实现对应的功能。总之,访问控制符通过控制声明的内容的访问权限,实现对于内容的隐藏,从而降低使代码的耦合性降低,降低项目的复杂度,并且方便实际项目中代码的维护。
--------------------------------------------------------------------------------------------------------------------------------------------------------------
static 修饰符
修饰符
修饰符的作用是让被修饰的内容具备特定的功能,在程序中合理使用修饰符可以在语法和功能上实现很多需要的效果。Java 语言中的修饰符主要有5个:static、final、native、abstract 和synchronized。这里首先讲解static、final 和native 的作用。
static 修饰符
static 关键字的中文意思是静态的,该修饰符可以修饰成员变量,成员常量和成员方法。使用该关键字修饰的内容,在面向对象中static 修饰的内容是隶属于类,而不是直接隶属于对象的,所以static 修饰的成员变量一般称作类变量,而static 修饰的方法一般称作类方法。另外,static 还可以修饰代码块,下面进行详细的介绍。
静态变量
static 修饰的变量称作静态变量。静态变量和一般的成员变量不同,一个类在加载到内存时,静态变量只初始化一次,也就是说所有对象的静态变量在内存中都只有一个存储位置,每个对象中的静态变量都指向内存中同一个地址,它是在所有的对象之间共享的数据。另外静态变量在引用时比较方便。
所以一般在需要实现以下两个功能时使用静态变量:
★在对象之间共享值时
★方便访问变量时

下面首先说一下非静态变量(没有static 修饰符修饰的成员变量)在内存中如何存储的。
示例代码如下:
//文件名Box.java
public class Box{
        int length;
        int width;
        int height;
        public Box(int l,int w,int h){
                length = l;
                width = w;
                height = h;
        }
}
//文件名TestBox.java
public class TestBox{
        public static void main(String[] args){
                Box a = new Box(10,20,30);
                Box b = new Box(40,20,10);
        }
}
说明:
非静态变量的值在每个对象中都有独立的存储空间,不同对象间这些值之间没有管理,也就是说每个对象都为内部的每个非静态的变量分配独立的存储空间,所以每个对象中非静态变量是隶属于对象,也就是说在每个对象中可能是不同的。简单介绍了非静态变量在对象中的存储以后,下面再来看一下静态变量是如何进行存储的。
示例代码如下:
//文件名StaticVar.java
public class StaticDemo{
        static int m;
        int n;
        char c;
}
//文件名TestStaticVar.java
public class TestStaticVar{
        public static void main(String[] args){
                StaticVar sv1 = new StaticVar();
                StaticVar sv2 = new StaticVar();
        }
}
说明:
对于StaticDemo 类型的对象sv1 和sv2 来说,由于使用默认的构造方法进行构造,所以每个成员变量都被初始化为对应数据类型的默认值,int 的默认值为0,char 的默认值为编号为0 的字符,而静态变量的存储和非静态变量的存储不同,在Java 虚拟机内部,第一次使用类时初始化该类中的所有静态变量,以后就不再进行初始化,而且无论创建多少个该类的对象,静态变量的存储在内存中都是独立于对象的,也就是Java 虚拟机单独为静态变量分配存储空间,所以导致所有的对象内部的静态变量在内存中存储时只有一个空间。这样就导致使用任何一个对象对该值的修改都是使该存储空间中的值发生改变,而其它对象在后续引用时就跟着发生了变化。静态变量就
是使用这样的方式在所有的对象之间进行数值共享的。
静态变量在实际使用时,可以通过只存储一次来节约存储空间,这个特性导致在类内部定义的成员常量一般都做成静态的,因为常量的值在每个对象中都是相同的,而且使用static 修饰也便于对成员常量的引用。
在类外部访问某类中静态变量(常量)的语法格式为:
类名.成员变量(常量)
例如:
StaticDemo.m
这样方便对于成员变量的访问。当然,语法上也不禁止使用:对象.成员变量,这样的语法格式进行访问,但是一般不推荐这样使用,而且有些类是无法创建对象的。
注意:static 关键字不能修饰成员方法或构造方法内部的变量。
静态方法
static 修饰的方法称作静态方法。静态方法和一般的成员方法相比,不同的地方有两个:一是调用起来比较方便,二是静态方法内部只能使用静态的成员变量。所以一般静态方法都是类内部的独立的功能方法。例如为了方便方法的调用,Java API中的Math类中所有的方法都是静态的,而一般类内部的static方法也是方便其它类对该方法的调用。
示例代码如下:
//文件名MyMath.java
public class MyMath{
        public static int max(int a,int b){
                return (a > b ? a : b);
        }
}
//文件名TestMyMath.java
public class TestMyMath{
        public static void main(String[] args){
                int m = 10;
                int n = 20;
                int k = MyMath.max(m,n);
        }
}
静态方法在类的外部进行调用时不需要创建对象,使用类名.方法名(参数)这样的语法格式进行调研,简化了代码的编写。使用静态方法时,需要特别注意的是静态方法内部使用该类的非静态成员变量,否则将出现语法错误。静态方法是类内部的一类特殊方法,只有在需要时才将对应的方法声明成静态的,一个类内部的方法一般都是非静态的。
静态代码块
静态代码块指位于类声明的内部,方法和构造方法的外部,使用static修饰的代码块。静态代码块在该类第一次被使用时执行一次,以后再也不执行。在实际的代码中,如果需要对类进行初始化的代码,可以写在静态代码块的内部。
示例代码如下:
//文件名StaticBlock.java
public class StaticBlock{
        static{
                System.out.println(“静态代码块!”);
        }
}
静态代码块是一种特殊的语法,熟悉该语法的特点,在实际程序中根据需要使用。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
final 修饰符
final
final 关键字是最终的、最后的意思,在程序中可以用来修饰类、成员变量和方法的声明,由该关键字修饰的内容都是不可变的。
final 数据
final 修饰的数据是常量,常量既可以出现在类的内部,也可以出现在方法或构造方法的内部。在程序中常量只能赋值一次。
其它说明可以参看前面的常量介绍。在程序中,一般类内部的成员常量为了方便调用,一般都使用static修饰符进行修饰。
示例代码如下:
/**
* 常量使用
*/
public class Student {
        /**性别*/
        int sex;
        /**男性*/
        public final static int MALE = 0;
        /**女性*/
        public final static int FEMALE = 1;
}

final 方法
final 关键字也可以修饰方法,final 修饰的方法称作最终方法,最终方法不能被覆盖,也就是不能在子类的内部重写该方法。
使用final 修饰方法,可以在一定程度上提高该方法的执行速度,应为在调用该方法时,就不需要进行覆盖的判断了。
final 类
final 关键字也可以修饰类,final 修饰的类称作最终类,最终类不能被继承,也就是该类不能有子类。
final 类内部的每个方法都是final 方法。
---------------------------------------------------------------------------------------------------------------------------------------------------------------
native
native 关键字是“本地的”意思,native 修饰的方法,只有方法的声明使用java 语言实现,而方法内部的代码都是在Java 虚拟机内部使用其它语言实现。一般native 的方法,都是和系统操作有关的方法,或者是基于底层实现效率比较高的方法,常见于系统类中。例如System 类的arraycopy 方法等。
----------------------------------------------------------------------------------------------------------------------------------------------------------------
this 和super
this 和super
下面再来介绍一下this 和super 关键字的使用。在程序中通过使用
this 和super 关键字,可以实现对于类内部很多内容方便的引用,也有助于理
解面向对象的实现原理,更方便的理解面向对象技术的内部实现。
this 关键字
this 关键字代表自身,在程序中主要的使用用途有以下几个方面:
★使用this 关键字引用成员变量
★使用this 关键字在自身构造方法内部引用其它构造方法
★使用this 关键字代表自身类的对象
★使用this 关键字引用成员方法

引用成员变量
在一个类的方法或构造方法内部,可以使用“this.成员变量名”这样的格式来引用成员变量名,有些时候可以省略,有些时候不能省略。首先看一下下面的代码:
/**
* 使用this 引用成员变量
*/
public class ReferenceVariable {
        private int a;
        public ReferenceVariable(int a){
                this.a = a;
        }
        public int getA(){
                return a;
        }
        public void setA(int a){
                this.a = a;
        } 
}
在该代码的构造方法和setA 方法内部,都是用this.a 引用类的成员变量。因为无论在构造方法还是setA 方法内部,都包含2 个变量名为a 的变量,一个是参数a,另外一个是成员变量a。按照Java 语言的变量作用范围规定,参数a 的作用范围为构造方法或方法内部,成员变量a 的作用范围是类的内部,这样在构造方法和setA 方法内部就存在了变量a 的冲突,Java 语言规定当变量作用范围重叠时,作用域小的变量覆盖作用域大的变量。所以在构造方法和setA方法内部,参数a 起作用。这样需要访问成员变量a 则必须使用this 进行引用。当然,如果变量名不发生重叠,则this 可以省略。但是为了增强代码的可读性,一般将参数的名称和成员变量的名称保持一致,所以this 的使用频率在规范的代码内部应该很多。
引用构造方法
在一个类的构造方法内部,也可以使用this 关键字引用其它的构造方法,这样可以降低代码的重复,也可以使所有的构造方法保持统一,这样方便以后的代码修改和维护,也方便代码的阅读。
下面是一个简单的示例:
/**
* 使用this 关键字引用构造方法
*/
public class ReferenceConstructor {
        int a;
        public ReferenceConstructor(){
                this(0);
        }
        public ReferenceConstructor(int a){
                this.a = a;
        }
}
这里在不带参数的构造方法内部,使用this 调用了另外一个构造方法,其中0 是根据需要传递的参数的值,当一个类内部的构造方法比较多时,可以只书写一个构造方法的内部功能代码,然后其它的构造方法都通过调用该构造方法实现,这样既保证了所有的构造是统一的,也降低了代码的重复。
在实际使用时,需要注意的是,在构造方法内部使用this 关键字调用其它的构造方法时,调用的代码只能出现在构造方法内部的第一行可执行代码。这样,在构造方法内部使用this 关键字调用构造方法最多会出现一次。
代表自身对象
在一个类的内部,也可以使用this 代表自身类的对象,或者换句话说,每个类内部都有一个隐含的成员变量,该成员变量的类型是该类的类型,该成员变量的名称是this,实际使用this 代表自身类的对象的示例代码如下:
/**
* 使用this 代表自身类的对象
*/
public class ReferenceObject {
        ReferenceObject instance;
        public ReferenceObject(){
                instance = this;
        }
        public void test(){
                System.out.println(this);
        }
}
在构造方法内部,将对象this 的值赋值给instance,在test 方法内部,输出对象this 的内容,这里的this 都代表自身类型的对象。
引用成员方法
在一个类的内部,成员方法之间的互相调用时也可以使用“this.方法名(参数)”来进行引用,只是所有这样的引用中this 都可以省略,所以这里就不详细介绍了。
super 关键字
super 关键字的中文意思是超级的,使用super 关键字可以在子类中
引用父类中的内容。主要的使用形式有以下几种:
在子类的构造方法内部引用父类的构造方法
在子类中调用父类中的成员方法
在子类中调用父类中的成员变量
引用父类构造方法
在构造子类对象时,必须调用父类的构造方法。而为了方便代码的编写,在子类的构造方法内部会自动调用父类中默认的构造方法。但是如果父类中没有默认的构造方法时,则必须手动进行调用。
使用super 可以在子类的构造方法内部调用父类的构造方法。可以在子类的构造方法内部根据需要调用父类中的构造方法。
使用super 关键字调用父类构造方法的示例代码如下:
//文件名:SuperClass.java
public class SuperClass {
        public SuperClass(){}
        public SuperClass(int a){}
}
//文件名:SubClass.java
public class SubClass extends SuperClass {
        public SubClass(){
                super(); //可省略
        }
        public SubClass(int a){
                super(a);
        }
        public SubClass(String s){
                super(); //可省略
        }
}

在该示例代码中,SubClass 继承SuperClass 类,在SubClass 类的构造方法内部可以使用super 关键字调用父类SubClass 的构造方法,具体调用哪个构造方法没有限制,可以在子类内部根据需要进行调用,只是根据调用的构造方法不同传入适当的参数即可。由于SubClass 类的父类SuperClass 内部有默认的构造方法,所以SubClass 的构造方法内部super()的代码可以省略。和使用this 关键字调用构造方法一样,super 调用构造方法的代码只能出现在 
子类构造方法中的第一行可执行代码。这样super 调用构造方法的代码在子类的
构造方法内部则最多出现一句,且不能和this 调用构造方法的代码一起使用。
引用父类成员方法
在子类中继承了父类中的成员方法,一般可以直接通过方法名使用,但是如果在子类中覆盖了父类的成员方法以后,如果需要在子类内部调用父类中被覆盖的成员方法时则不能直接调用了,这样就又需要使用super 关键字了。
示例代码如下:
//文件名:SuperClass2.java
public class SuperClass2 {
        public void test(){}
        public void print(int a){
                System.out.println("SuperClass2: " + a);
        }
}
//文件名:SubClass2
public class SubClass2 extends SuperClass2 {
        public void print(int a){
                super.print(a);
                System.out.println("SubClass2");
        }
        public void t(){
                super.test(); //super 可省略
                super.print(0); //不可省略
        }
}
引用父类成员变量
在子类中如果引用父类的成员变量,也可以使用“super.成员变量”来引用,只是一般成员变量的覆盖是没有意义的,所以这个时候都可以直接使用成员变量名进行引用,所以这里的super 都可以省略。
注意的问题:最后,在实际使用this 和super 时,除了上面介绍到的需要注意的问题以外,还需要特别注意的是,this 和super 都是非静态的,所以这两个关键字都无法在静态方法内部进行使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值