java.docx
- 文档编号:28987157
- 上传时间:2023-07-20
- 格式:DOCX
- 页数:18
- 大小:24.63KB
java.docx
《java.docx》由会员分享,可在线阅读,更多相关《java.docx(18页珍藏版)》请在冰豆网上搜索。
java
Java访问修饰符和非访问修饰符
实验课程名称:
Java语言程序设计
开课名称:
计算机科学与技术学院
指导老师姓名:
祁明龙
学生姓名:
黄超
学生专业班级:
软件工程sy1001班
1、Java访问控制修饰符
1.1访问控制修饰符介绍
访问控制修饰符是限定一个名字的可访问性,这里的名字可以是类、成员属性和成员方法。
也就是说,它是限定类、属性或方法是否可以被程序里的其他部分访问和调用。
可访问性是一种在编译时确定的静态特性,在编译时就确定了一个名字在什么范围内可以被访问,从而限制一个名字的访问权限。
访问控制用来实现面向对象的四个基本特征中的封装机制。
Java语言提供了四种访问权限:
private(私有)、默认、protected(受保护)、public(公有)。
当变量、方法和类被其中不同的关键字修饰时,会有不同的访问权限和使用范围,访问控制修饰符的权限如表1所示。
表1访问控制修饰符
位置
private
Protected
Public
同一个类
是
是
是
同一个包内的子类
否
是
是
不同包内的子类
否
是
是
不同包并且不是子类
否
否
是
private关键字的访问控制权限最高,使用private关键字修饰的方法
或者属性属于私有类型,只能被类本身访问和修改,其他类无权使用。
friendly关键字是默认的访问修饰符。
使用它修饰的类可以被类自身和同一个包中的类访问。
protected关键字修饰的方法或者属性是保护类型的,即除了被类自身和同一个包中的类访问外,还可以被其他包中的子类访问。
public关键字的访问权限最低,public关键字修饰的类,方法或者属性可以被所有类访问。
通过使用访问控制修饰符来限定对对象私有属性的访问,可以获得3个重要好处。
防止对封装数据的未授权访问。
有助于保证数据完整性。
当类的私有实现细节必须改变时,可以限制发生在整个应用程序中的“连锁反应”。
1.2访问权限修饰符修饰成员变量和方法
public:
修饰的类、属性或方法可以被任何类访问,无论它们是否在同一个包下,没有任何限制。
类中被设定为public的方法是这个类对外的接口。
每个Java程序的主类都必须是public类。
protected:
修饰的方法或者属性可以被其他包中的子类访问。
当类的属性或者方法希望被其子类访问,而不希望被其他类访问的时候,可以将属性和方法设置为protected类型。
例如:
publicclassA{
protectedintweight=0;
protectedintf(inta,intb)
{
System.out.println(a+b);
returna+b;
}
}
假设B与A在同一个包中(packagePackLun1),则
publicclassB{
voidprint()
{
Aa=newA();
a.weight=100;
a.f(23,5);
}
publicstaticvoidmain(Stringargs[])
{
Bb=newB();
b.print();
}
}
程序结果:
28
Private:
使用private修饰的类成员,只能被该类自身的方法访问和修改,而不能被任何其他类(包括该类的子类)访问和引用。
因此,private修饰符具有最高的保护级别。
例如:
classTest
{
privateintmoney;
Test()
{
money=2000;
}
privateintgetMoney()
{
returnmoney;
}
publicstaticvoidmain(Stringargs[])
{
Testte=newTest();
te.money=3210;//合法
intm=te.getMoney();//合法
System.out.println("money="+m);
}
}
程序结果:
money=3210
1.3访问权限修饰符修饰类
表2访问修饰符修饰类
访问修饰符
名称
说明
备注
public
可以被所有类访问(使用)
public类必须定义在和类名相同的同名文件中
private
修饰内部类
例如:
publicA.java
packagePackLun1;
publicclasspublicA{//公共类
intweight=100;
voidg(inta,intb)
{
System.out.println(a*b);
}
}
friendly.java
packagePackLun1;
classfriendlyB{
intweight=100;
voidg(inta,intb)
{
System.out.println(a*b);
}
}
C.java
packagePackLun1;
publicclassC{
privateclassD{//内部类
voidg(inta,intb)
{
System.out.println(a*b);
}
}
publicstaticvoidmain(Stringargs[])
{
publicAa=newpublicA();
friendlyBb=newfriendlyB();
Cc=newC();
Dd=c.newD();
a.g(5,6);
b.g(5,6);
d.g(5,6);
}
}
程序运行结果:
30
30
30
1.4访问权限修饰符与继承
这里的访问修饰符指的是修饰成员变量和方法。
可以分为两种情况:
1.4.1子类与父类在同一包中
此时只有声明为private的变量与方法不能被继承(访问)
例如:
packagePackLun1;
classFather
{
privateintmoney;
intweight=100;
}packagePackLun1;
classSonextendsFather
{
voidf()
{
money=10000;//非法
weight=100;//合法
}
}
1.4.2子类与父类不在同一包中
此时private与friendly均不能被继承(访问),protected与public可以。
例如:
Father.java
packagePackLun1;
publicclassFather
{
intheight;
protectedintmoney=120;
publicintweight;
protectedintgetMoney()
{
returnmoney;
}
voidsetMoney(intnewMoney)
{
money=newMoney;
}
}
Son.java
packagePackLun2;
importPackLun1.Father;
publicclassSonextendsFather
{
voidf()
{
money=10000;//合法
//height=170;//非法,height为friendly修饰的变量
System.out.println(money);//输出结果是10000
//setMoney(300);//非法
intnumber=getMoney();//合法
System.out.println(number);//输出结果是10000
}
publicstaticvoidmain(Stringargs[])
{
Sonsss=newSon();
sss.f();
}
}
程序结果:
10000
10000
所以,访问权限修饰符权限从高到低为public,protected,
private。
2、Java非访问控制修饰符
2.1static的用法
2.1.1static变量
按照是否静态的对类成员变量进行分类可分两种:
一种是被static修饰的变量,叫静态变量或类变量;另一种是没有被static修饰的变量,叫实例变量。
两者的区别是:
对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(但是这是不推荐的)。
对于实例变量,没创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响(灵活)。
2.1.2静态方法
静态方法可以直接通过类名调用,任何的实例也都可以调用,因此静态方法中不能用this和super关键字,不能直接访问所属类的实例变量和实例方法(就是不带static的成员变量和成员成员方法),只能访问所属类的静态成员变量和成员方法。
因为实例成员与特定的对象关联!
这个需要去理解,想明白其中的道理,不是记忆!
!
!
因为static方法独立于任何实例,因此static方法必须被实现,而不能是抽象的abstract。
2.1.3static代码块
static代码块也叫静态代码块,是在类中独立于类成员的static语句块,可以有多个,位置可以随便放,它不在任何的方法体内,JVM加载类时会执行这些静态的代码块,如果static代码块有多个,JVM将按照它们在类中出现的先后顺序依次执行它们,每个代码块只会被执行一次。
例1静态变量:
classCount{
privateintserialNumber;
publicstaticintcounter=0;
publicCount(){
counter++;
serialNumber=counter;
}
publicintgetSerialNumber(){
returnserialNumber;
}
}
publicclassTestStaticVar{
publicstaticvoidmain(String[]args){
Counter[]cc=newCount[10];
for(inti=0;i cc[i]=newCount(); System.out.println("cc["+i+"].serialNumber="+cc[i].getSerialNumber()); } } } 运行结果如下: cc[0].serialNumber=1 cc[1].serialNumber=2 cc[2].serialNumber=3 cc[3].serialNumber=4 cc[4].serialNumber=5 cc[5].serialNumber=6 cc[6].serialNumber=7 cc[7].serialNumber=8 cc[8].serialNumber=9 cc[0].serialNumber=10 java中没有全局变量,但静态变量是一个类的所有实例对象中都可以访问的变量,有点类似与其他语言中的全局变量。 静态变量只依附于类,而与类的实例对象无关,所以对于不是private类型的静态变量,我们可以在该类外直接用类名调用,而不像实例变量那样需要通过实例对象才能访问。 例如,我们可以在下面的类中直接对上例中的count类的静态变量counter进行访问: publicclassOtherClass{ publicvoidincrementNumber(){ Count.counter++; } } 例静态代码块: classStaticCode { staticStringcountry="StaticCodeString"; { System.out.println("ClassStaticCodeblockisloading! "); } static { country="china"; System.out.println("countryinit="+country); System.out.println("ClassStaticCodestaticblockisloading! "); } StaticCode() { System.out.println(country); } voidShowMe() { System.out.println(country); } } classStaticCode2extendsStaticCode { staticStringcountry="StaticCode2String"; { System.out.println("ClassStaticCode2blockisloading! "); } static { System.out.println("ClassStaticCode2staticblockisloading! "); } StaticCode2() { System.out.println(country); } voidShowMe() { System.out.println(country); } } classtest { static { System.out.println("Classtestisloading! "); } publicstaticvoidmain(String[]args) { System.out.println("Beginexecutingmainmethod! "); //StaticCodest1=newStaticCode(); StaticCodest=newStaticCode2(); st.ShowMe(); } } 程序执行结果: ThecustomerIDis20040 2.2final的用法 final在Java中并不常用,然而它却为我们提供了诸如在C语言中定义常量的功能,不仅如此,final还可以让你控制你的成员、方法或者是一个类是否可被覆写或继承等功能,这些特点使final在Java中拥有了一个不可或缺的地位,也是学习Java时必须要知道和掌握的关键字之一。 2.2.1final成员 当你在类中定义变量时,在其前面加上final关键字,那便是说这个变量一旦被初始化便不可改变,这里不可改变的意思对基本类型来说是其值不可变,而对于对象变量来说其引用不可再变。 其初始化可以在两个地方,一是其定义处,也就是说在final变量定义时直接给其赋值,二是在构造函数中。 这两个地方只能选其一,要么在定义时给值,要么在构造函数中给值,不能同时既在定义时给了值,又在构造函数中给另外的值。 下面这段代码演示了这一点: ThecustomerIDis20040 此程序很简单的演示了final的常规用法。 在这里使用在构造函数中进行初始化的方法,这使你有了一点灵活性。 如Bat的两个重载构造函数所示,第一个缺省构造函数会为你提供默认的值,重载的那个构造函数会根据你所提供的值或类型为final变量初始化。 然而有时你并不需要这种灵活性,你只需要在定义时便给定其值并永不变化,这时就不要再用这种方法。 在main方法中有两行语句注释掉了,如果你去掉注释,程序便无法通过编译,这便是说,不论是i的值或是list的类型,一旦初始化,确实无法再更改。 然而b可以通过重新初始化来指定i的值或list的类型,输出结果中显示了这一点: I=100ListType: classjava.util.LinkedList I=23ListType: classjava.util.ArrayList 还有一种用法是定义方法中的参数为final,对于基本类型的变量,这样做并没有什么实际意义,因为基本类型的变量在调用方法时是传值的,也就是说你可以在方法中更改这个参数变量而不会影响到调用语句,然而对于对象变量,却显得很实用,因为对象变量在传递时是传递其引用,这样你在方法中对对象变量的修改也会影响到调用语句中的对象变量,当你在方法中不需要改变作为参数的对象变量时,明确使用final进行声明,会防止你无意的修改而影响到调用方法。 另外方法中的内部类在用到方法中的参变量时,此参变也必须声明为final才可使用,如下代码所示: publicclassINClass{ voidinnerClass(finalStringstr){ classIClass{ IClass(){ System.out.println(str); } } IClassic=newIClass(); } publicstaticvoidmain(String[]args){ INClassinc=newINClass(); inc.innerClass("Hello"); } } 2.2.2final方法 将方法声明为final,那就说明你已经知道这个方法提供的功能已经满足你要求,不需要进行扩展,并且也不允许任何从此类继承的类来覆写这个方法,但是继承仍然可以继承这个方法,也就是说可以直接使用。 另外有一种被称为inline的机制,它会使你在调用final方法时,直接将方法主体插入到调用处,而不是进行例行的方法调用,例如保存断点,压栈等,这样可能会使你的程序效率有所提高,然而当你的方法主体非常庞大时,或你在多处调用此方法,那么你的调用主体代码便会迅速膨胀,可能反而会影响效率,所以你要慎用final进行方法定义。 2.2.3final类 当你将final用于类身上时,你就需要仔细考虑,因为一个final类是无法被任何人继承的,那也就意味着此类在一个继承树中是一个叶子类,并且此类的设计已被认为很完美而不需要进行修改或扩展。 对于final类中的成员,你可以定义其为final,也可以不是final。 而对于方法,由于所属类为final的关系,自然也就成了final型的。 你也可以明确的给final类中的方法加上一个final,但这显然没有意义。 下面的程序演示了final方法和final类的用法: 如果类的成员变量被定义为final,则变量一经赋值就不能改变,所以可以通过申明final变量并同时赋初值来定义常量,并且变量名一般大写。 例如: finalintNUMBER=100 如果在程序中要改变final变量的值,则将产生编译时错误。 如果类的final变量在声明时没有赋初值,则在所属类的每个都构造函数方法中都必须对该变量赋值。 如果未赋值的final变量时局部变量,则可以再所属方法体的任何位置对其赋值,但只能赋值一次。 例: 声明类的final变量并在构造方法中赋值。 classCustomer{ privatefinallongcustomerID; privatestaticlongcounter=200401; publicCustomer(){ customerID=counter++; } publiclonggetID(){ returncustomerID; } publicstaticvoidmain(String[]args){ Customer[]cc=newCustomer[5]; for(inti=0;i cc[i]=newCustomer(); System.out.println("ThecustomerIDis"+cc[i].getID()); } } } 运行结果: ThecustomerIDis200401 ThecustomerIDis200402 ThecustomerIDis200403 ThecustomerIDis200404 ThecustomerIDis200405 2.3abstract的用法 Abstract是Java中的一个重要关键字,可以用来修饰一个类或者一个方法。 修饰一个方法时,表示该方法只有特征签名(signature),没有具体实现,而是把具体实现留给继承该类的子类。 一个类中只要有一个abstract方法,那么这个类就要被声明为abstract,但是其中可以有非abstract方法。 abstract类可以使得类的设计者能够创建方法的原型,而真正的实现留给使用这个类的人。 继承一个abstract类的子类,要么实现父类的所有abstract方法,要么也声明为abstract类,这时仍然可以保留一些abstract方法,把具体实现留给下一级的子类。 2.3.1abstract修饰类 abstract修饰类时,该类不能手动创建对象(JVM可以创建抽象类的对象),但是可以声明抽象类型的引用。 如下所示 publicclassTestAbstract1{ publicstaticvoidmain(String[]args){ //Animala=newAnimal();//error Animala=null;a=newDog();}}abstractclassAnimal{}classDogextendsAnimal{} 2.3.1abstract修饰类 abstract修饰方法时,有方法名的定义,但没有具体实现,也就是说只是定义了一个方法能够实现什么功能,但没有说具体怎样做。 这样做的好处就是允许方法的定义和实现分开。 抽象方法的定义如下所示: 抽象方法的好处是允许方法的定义和实现分开。 abstractclassAnimal{publicabstractvoideat();} 抽象类与抽象方法的关系是: 有抽象方法的类一定是抽象类,抽象类却不一定有抽象方法。 抽象类是用来继承的,一个类继承了抽象类,则必须实现该抽象类中的所有的抽象方法,否则该类也是抽象类。 如下所示: abstractclassAnimal{publicvoidrun(){}//该方法不是抽象方法publicabstractvoidsleep();publicabstractvoideat();} classDogextendsAnimal{publicvoidsleep(){System.out.println("Dogsleep.");}publicvoideat(){System.out.println("Dogeat.");}} abstractclassCatextendsAnimal{publicvoideat(){System.out.println("Cateat.");}} 可以声明父类类型子类对象,利用多态调用抽象方法,如下所示: publicclassTestAbstract1{publicstaticvoidmain(String[]a
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- java
![提示](https://static.bdocx.com/images/bang_tan.gif)