java修饰符.docx
- 文档编号:30285828
- 上传时间:2023-08-13
- 格式:DOCX
- 页数:22
- 大小:24.60KB
java修饰符.docx
《java修饰符.docx》由会员分享,可在线阅读,更多相关《java修饰符.docx(22页珍藏版)》请在冰豆网上搜索。
java修饰符
Java访问修饰符和非访问修饰符
实验课程名称:
Java语言程序设计
开课名称:
计算机科学与技术学院
指导老师姓名:
祁明龙
学生姓名:
毛会君
学生专业班级:
软件工程1003班
1、Java访问控制修饰符
1.1访问控制修饰符介绍
访问控制修饰符是限定一个名字的可访问性,这里的名字可以是类、成员属性和成员方法。
也就是说,它是限定类、属性或方法是否可以被程序里的其他部分访问和调用。
可访问性是一种在编译时确定的静态特性,在编译时就确定了一个名字在什么范围内可以被访问,从而限制一个名字的访问权限。
访问控制用来实现面向对象的四个基本特征中的封装机制。
Java语言提供了四种访问权限:
private(私有)、friendly(友好)或默认、protected(受保护)、public(公有)。
如果把访问控制比喻成房间的门,那么访问权限就是门的状态。
如果再把包比作楼房的一个单元,每个单元都有一个共用的有对讲功能的防盗门,正常情况下只有本单元的住户才能凭钥匙打开此防盗门进入单元,其他来访者只能在住户确认身份后通过对讲机上的开关进入单元,那么访问控制权限就容易解释了。
所以当变量、方法和类被其中不同的关键字修饰时,会有不同的访问权限和使用范围,访问控制修饰符的权限如表1所示。
表1访问控制修饰符
位置
private
Friendly
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(3,4);
}
publicstaticvoidmain(Stringargs[])
{
Bb=newB();
b.print();
}
}
程序结果:
7
Friendly:
Java中friendly关键字是一个默认值,也就是说,如果不
在程序中明确地指明类、方法或者属性的类型,那么它被默认为是friendly类型,说明它具有默认的访问控制特性。
friendly类型修饰的属性和方法除了可以在自身类中被访问和修改外,还可以被同一个包下的类修改或访问,但是不能被其他包中的类使用,即使其他包中有该类的子类。
在访问权限修饰符修饰成员变量和方法中,用法同protected,区别在下文1.3,1.4中。
例如:
publicclassA{
intweight=0;
intf(inta,intb)
{
System.out.println(a+b);
returna+b;
}
}
假设B与A在同一个包中(packagePackLun1),则
publicclassB{
voidprint()
{
Aa=newA();
a.weight=100;
a.f(3,4);
}
publicstaticvoidmain(Stringargs[])
{
Bb=newB();
b.print();
}
}
程序结果:
7
Private:
使用private修饰的类成员,只能被该类自身的方法访问和修改,而不能被任何其他类(包括该类的子类)访问和引用。
因此,private修饰符具有最高的保护级别。
例如:
classTest
{
privateintmoney;
Test()
{
money=2000;
}
privateintgetMoney()
{
returnmoney;
}
publicstaticvoidmain(Stringargs[])
{
Testte=newTest();
te.money=3000;//合法
intm=te.getMoney();//合法
System.out.println("money="+m);
}
}
程序结果:
money=3000
实际上,把重要的数据修饰为private,然后写一个public的函数访问它,正好体现了OOP的封装特性,是OOP安全性的体现。
1.3访问权限修饰符修饰类
不能用protected和private修饰类(可修饰内部类)。
用friendly修饰的类叫友好类,在另外一个类中使用友好类创建对象时,要保证它们在同一包中。
具体如下表所示
表2访问修饰符修饰类
访问修饰符
名称
说明
备注
public
可以被所有类访问(使用)
public类必须定义在和类名相同的同名文件中
friendly
可以被同一个包中的类访问(使用)
默认的访问权限,可以省略此关键字,可以定义在和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,friendly,
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静态变量:
packagePackLun1;
publicclassStatic{
static{
intx=5;
}
staticintx,y;
publicstaticvoidmain(Stringargs[]){
x--;
myMethod();
System.out.println(x+y+++x);
}
publicstaticvoidmyMethod(){
y=x+++++x;
}
}
分析如下:
首先,是静态变量与静态块的执行顺序问题。
接下来才是变量作用域与全局变量之间的关系问题。
静态块中定义的变量只会在他的作用域范围内部有效。
而且只要是重新定义的,就不会受全局变量的影响。
也就是说,main方法中的x--仅仅是针对全局变量的。
由于Java会将该变量初始化,此时,i--=0,但是在下次用到i时,其值已经变为-1。
接下来就是给y赋值。
同理x++的值应该是-1。
但是在下次使用i时,其值已经变为0了。
而对“0”累加的结果就是“1”,因此,y的值也是“0”。
由此推断,最后结果为“3”
例2静态方法:
packagePackLun1;
classStaticVary{
staticintx;
inty;
publicintx(){
returnx;
}
publicvoidsetx(intnewx){
x=newx;
}
publicvoidsety(intnewy){
y=newy;
}
}
packagePackLun1;
publicclassStaticVary_test{
publicstaticvoidmain(Stringargs[]){
StaticVaryp1=newStaticVary();
StaticVaryp2=newStaticVary();
p1.setx
(1);
p2.setx(3);
p1.sety(8);
p2.y=10;
System.out.println("***static:
xis****************");
System.out.println("p1.x="+p1.x());
System.out.println("p2.x="+p2.x);
System.out.println("***********************");
System.out.println("*****obiect:
yis******************");
System.out.println("p1.y="+p1.y);
System.out.println("p2.y="+p2.y);
}
}
例3静态代码块:
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();
}
}
程序执行结果:
Classtestisloading!
Beginexecutingmainmethod!
countryinit=china
ClassStaticCodestaticblockisloading!
ClassStaticCodestatic2blockisloading!
ClassStaticCodeblockisloading!
china
ClassStaticCode2blockisloading!
StaticCode2String
StaticCode2String
分析:
类的执行顺序是:
父类静态代码→子类静态代码→父类非静态代码块→父类构造→子类非静态代码块→子类构造
2.2final的用法
final在Java中并不常用,然而它却为我们提供了诸如在C语言中定义常量的功能,不仅如此,final还可以让你控制你的成员、方法或者是一个类是否可被覆写或继承等功能,这些特点使final在Java中拥有了一个不可或缺的地位,也是学习Java时必须要知道和掌握的关键字之一。
2.2.1final成员
当你在类中定义变量时,在其前面加上final关键字,那便是说这个变量一旦被初始化便不可改变,这里不可改变的意思对基本类型来说是其值不可变,而对于对象变量来说其引用不可再变。
其初始化可以在两个地方,一是其定义处,也就是说在final变量定义时直接给其赋值,二是在构造函数中。
这两个地方只能选其一,要么在定义时给值,要么在构造函数中给值,不能同时既在定义时给了值,又在构造函数中给另外的值。
下面这段代码演示了这一点:
packagePackLun1;
importjava.util.List;
importjava.util.ArrayList;
importjava.util.LinkedList;
publicclassBat{
finalPI=3.14;//在定义时便给址值
finalinti;//因为要在构造函数中进行初始化,所以此处便不可再给值
finalListlist;//此变量也与上面的一样
Bat(){
i=100;
list=newLinkedList();
}
Bat(intii,Listl){
i=ii;
list=l;
}
publicstaticvoidmain(String[]args){
Batb=newBat();
b.list.add(newBat());
//b.i=25;
//b.list=newArrayList();
System.out.println("I="+b.i+"ListType:
"+b.list.getClass());
b=newBat(23,newArrayList());
b.list.add(newBat());
System.out.println("I="+b.i+"ListType:
"+b.list.getClass());
}
}
此程序很简单的演示了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,那就说明你已经知道这个方法提供的功能已经满足你要求,不需要进行扩展,并且也不允许任何从此类继承的类来覆写这个方法,但是继承仍然可以继承这个方法,也就是说可以直接使用。
另外
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- java 修饰
![提示](https://static.bdocx.com/images/bang_tan.gif)