java修饰符_Java修饰符

本文详细介绍了Java中的访问修饰符(public, default, protected, private)及其应用,特别是protected的使用场景。同时,讨论了非访问修饰符如abstract, static, final的作用和限制,包括它们在抽象类、接口、方法和变量中的应用。通过示例代码解释了不同修饰符下的访问权限和继承规则。
摘要由CSDN通过智能技术生成

一、访问修饰符

1.顾名思义,"访问修饰符"就是和访问权限有关得修饰符。

JAVA 的类(外部类)有 2 种访问权限: public、default。

而方法和变量有 4 种:public、default、protected、private。

其中默认访问权限和 protected 很相似,有着细微的差别。

public 意味着任何地方的其他类都能访问。

default 则是同一个包的类可以访问。

protected 表示同一个包的类可以访问,其他的包的该类的子类也可以访问。

private 表示只有自己类能访问。

2.这里重点说一下受保护的访问修饰符-protected

protected 需要从以下两个点来分析说明:

子类与基类在同一包中:被声明为 protected 的变量、方法和构造器能被同一个包中的任何其他类访问;

子类与基类不在同一包中:那么在子类中,子类实例可以访问其从基类继承而来的 protected 方法,而不能访问基类实例的protected方法。

package p1;public classFather1 {protected void f() {} //父类Father1中的protected方法

}

package p1;public classSon1 extends Father1 {}

package p11;public classSon11 extends Father1{}

package p1;public classTest1 {public static voidmain(String[] args) {

Son1 son1= newSon1();

son1.f();//Compile OK ----(1)

son1.clone(); //Compile Error ----(2)

Son11 son= newSon11();

son11.f();//Compile OK ----(3)

son11.clone(); //Compile Error ----(4)

}

}

对于上面的示例,首先看(1)(3),其中的f()方法从类Father1继承而来,其可见性是包p1及其子类Son1和Son11,而由于调用f()方法的类Test1所在的包也是p1,因此(1)(3)处编译通过。其次看(2)(4),其中的clone()方法的可见性是java.lang包及其所有子类,对于语句"son1.clone();"和"son11.clone();",二者的clone()是继承了Object类的方法,在类Son1、Son11中是可见的,但对Test1是不可见的,因此(1)(3)处编译不通过。

package p2;classMyObject2 {protected voidsay() {

System.out.println("我是父类的say方法!")

}

}

package p22;public classTest2 extends MyObject2 {public static voidmain(String args[]) {

MyObject2 obj= newMyObject2();

obj.say();//Compile Error ----(1)

Test2 tobj= newTest2();

tobj.say();//Complie OK ----(2)

}

}

对于(1)而言,say()方法来自于类MyObject2本身,因此其可见性为包p2及MyObject2的子类,虽然Test2是MyObject2的子类,但在Test2中不能访问基类MyObject2的protected方法say(),因此编译不通过;对于(2)而言,由于在Test2中访问的是其本身实例的从基类MyObject2继承来的的say(),因此编译通过。

3.访问修饰符中一些值得注意得地方:

Private 访问修饰符的使用主要用来隐藏类的实现细节和保护类的数据;

被声明为 public 的类、方法、构造方法和接口能够被任何其他类访问;

protected 访问修饰符不能修饰类和接口,方法和成员变量能够声明为 protected,但是接口的成员变量和成员方法不能声明为 protected;

二、非访问修饰符

1.abstract

可以修饰:方法  类   接口

【抽象类】

①.使用abstract关键字修饰类,称为抽象类

②.抽象类不能被实例化

【抽象方法】

①.被abstract修饰的没有方法体的方法

②.非抽象类继承抽象类,那么子类必须重写父类所有的抽象方法

③.抽象方法必须在抽象类中,但抽象类中不都是抽象方法

【接口】

①接口定义时使用interface关键字,默认用abstract修饰此关键字了;

②接口里的方法即使不写abstract依然是抽象方法,因为默认使用abstract修饰

2.static

可以修饰: 方法 属性  内部类(不可修饰外部类)

①.static修饰的属性 (静态属性)也叫类属性

②.static修饰的方法(静态方法)也叫类方法

③.推荐使用:类名.属性名 类名.方法名()来调用   (也可以使用对象调用)但不推荐

④.类属性和类方法是属于类的,在类加载时就加载,成员属性和成员方法在对象创建时才加载

因此静态属性和静态方法先于非静态属性和方法, 所以静态方法中不能调用非静态属性,非静态方法可以调用静态属性

⑤.静态方法不能使用this,super关键字;因为他两个代指子类对象和父类对象而静态比对象加载的早

⑥.由于类属性和类方法是属于类的,因此只会在类装载时产生一份,因此该类的多个实例只能使用同一个静态属性和方法(下面代码辅助理解该条)

public classDemo03_Static {//定义静态属性和静态方法

public static int a = 1;public static voidadd() {

a++;

}//定义成员属性和方法

public int b = 1;public voidadd1(){

b++;

}

}

public classDemo03_Static2 {public static voidmain(String[] args) {

//调用静态方法改变静态属性

Demo03_Static d1 = newDemo03_Static();

d1.add();//本来应该使用Demo03_Static.add();来调用静态方法这里为了方便理解没有使用

System.out.println(d1.a);//本来应该使用Demo03_Static.a;来调用静态属性

Demo03_Static d2= newDemo03_Static();

d2.add();//同上

System.out.println(d2.a);//调用成员方法改变成员属性

System.out.println("----------------------------------");

Demo03_Static d3= newDemo03_Static();

d3.add1();

System.out.println(d3.b);

Demo03_Static d4= newDemo03_Static();

d4.add1();

System.out.println(d4.b);

}

}

运行结果:

e1040e5304eb8ccab1a3a52780eb4651.png

※⑦.父类中的静态方法可以被继承、但不能被子类重写。

※⑧.如果在子类中写一个和父类中一样的静态方法,那么该静态方法由该子类特有,两者不构成重写关系。

public classDemo03_Static {//定义静态属性和方法

public static int a = 1;public static voidadd() {

a++;

System.out.println("父类的静态方法!");

}

}

public class Demo03_StaticSon extendsDemo03_Static{public static void add(){//√,是子类自己的静态方法,和父类的方法不构成重写

System.out.println("调用子类和父类同名的静态方法");}/*public void add(){//×,不能和父类静态方法重名

}*/

public static voidmain(String[] args) {

Demo03_Static d= newDemo03_StaticSon();

d.add();//测试能否重写父类的静态方法(多态本来是调用子类重写的父类方法,但是若调用父类自己的方法,说明没有重写该方法);}

}

运行结果:

60650d0278cb0695464f0d92de5cf092.png

3.final

可以修饰:方法  属性  局部变量  类(非抽象类)

1.final修饰的类为最终类,不能被继承

2.final修饰的方法不能被重写,但可以被继承

3.final修饰的变量不能被修改为常量

4.final以及final static修饰的变量的初始化方式:

//-----------------成员变量------------------//

//初始化方式一,在定义变量时直接赋值

private final int i = 3;//初始化方式二,声明完变量后在构造方法中为其赋值//如果采用用这种方式,那么每个构造方法中都要有j赋值的语句

private final intj;publicFinalTest() {

j= 3;

}//如果取消该构造方法的注释,程序就会报错,因此它没有为j赋值

/*public FinalTest1(String str) {

}*/

//为了方便我们可以这样写

publicFinalTest(String str) {this(); //调用无参构造器

}//下面的代码同样会报错,因为对j重复赋值

/*public FinalTest1(String str1, String str2) {

this();

j = 3;

}*/

//初始化方式三,声明完变量后在构造代码块中为其赋值//如果采用此方式,就不能在构造方法中再次为其赋值//构造代码块中的代码会在构造函数之前执行,如果在构造函数中再次赋值,//就会造成final变量的重复赋值

private final intk;

{

k= 4;

}//-----------------类变量(静态变量)------------------//

//初始化方式一,在定义类变量时直接赋值

public final static int p = 3;//初始化方式二,在静态代码块中赋值//成员变量可以在构造函数中赋值,但是类变量却不可以。//因此成员变量属于对象独有,每个对象创建时只会调用一次构造函数,//因此可以保证该成员变量只被初始化一次;//而类变量是该类的所有对象共有,每个对象创建时都会对该变量赋值//这样就会造成变量的重复赋值。

public final static intq;static{

q= 3;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值