Java(11)Java修饰符

Java修饰符

Java修饰符分为两大类:

  • 访问修饰符:default、private、public、protected
  • 非访问修饰符:static、final、abstract、synchronized和volatile

访问修饰符

  • public(修饰类、变量、方法、接口)
  • default(修饰类、变量、方法、接口)
  • private(修饰、变量、方法、接口
  • protected(修饰、变量、方法、接口)//被划掉的不能被修饰

private-->default-->protected-->public (访问权限大小)

修饰符 当前类 同一包内 子孙类(同一包) 子孙类(不同包) 其他包
public
protected ✅/❌
default(缺省)
private

访问修饰符是用来控制被修饰的东西的访问权限的,下面是访问修饰符的访问控制表:

可以看到,从private到default到protected到public,权限是越来越大的。private给予的权限最小,只有当前类可以使用。

private访问修饰符

修饰对象:private用来修饰变量和方法

范围:被private修饰的变量和方法只能为当前类使用

声明为private的变量只能通过类中公共的 getter 方法被外部类访问,如:

  • Inner.java源文件(与下面文件在同一个包中)
public class Inner {
	private int age=23;
	public void SetAge(int age) {
		this.age=age;
	}
	public int GetAge() {
		return age;
	}
}
  • Outter.java源文件:
public class Outter{
	public static void main(String[] args) {
		Inner a= new Inner();
		a.SetAge(50);    //Outter类修改Inner类private声明的变量
		System.out.println(a.GetAge());  //访问private声明的变量
	}
}
default访问修饰符(缺省)

修饰对象:default用来修饰类、变量、方法、接口

范围:被private修饰的变量和方法只能同一个包的类(包括子孙类)使用

  • 缺省修饰的变量不能被外包类访问案例
package PackageOne;

public class HelloOne {
    int age=21;
}
package PackageTwo;

import PackageOne.HelloOne;

public class HelloTwo extends HelloOne {
    public static void main(String[] args) {
        HelloTwo b=new HelloTwo();
        System.out.println(b.age);
        //报错:'age' is not public in 'PackageOne.HelloOne'. Cannot be accessed from outside package
    }
}
protected访问修饰符

protected可修饰变量、方法(包括构造方法),不能修饰类。

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

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

  • 案例
package p1;
public class Father1 {
    protected void f() {
    	System.out.println("这是来自父类protected声明的方法");
    }
}
//------------------------------

package p1;
public class Son1 extends Father1 {
	public static void main(String[] args) {
		Father1 a=new Father1();
		a.f();  //输出:这是来自父类protected声明的方法
		Son1 b=new Son1();
		b.f();  //输出:这是来自父类protected声明的方法
	}

}
//-------------------------------

package p2;
import p1.Father1;
public class Son2 extends Father1{
	public static void main(String[] args) {
		Father1 a=new Father1();
		//a.f();  此步会编译报错(a是父类实例,而Son2子类与父类不在同一个包中) 
		Son2 b = new Son2();
		b.f();  //输出:这是来自父类protected声明的方法
	}
}
public访问修饰符

方法和属性前有public修饰,可以被任意包内的类访问。 另外,类要想被其他包导入,必须声明为public。被public修饰的类,类名必须与文件名相同。


非访问修饰符

static非访问修饰符

static可以概括为一句话:方便在没有创建对象的情况下进行调用。也就是说:被static关键字修饰的不需要创建对象去调用,直接根据类名就可以去访问

static修饰后的成员会随着类的加载而加载,优先于对象存在,被所有对象共享。

static关键字修饰成员变量(不能修饰局部变量)、方法、代码块、内部类

package test;

public class HelloJimmy {
    public static int a = 10;

    public static void fun1() {
        System.out.println("Hello Krystal");
    }
}

class Person {
    public static void main(String[] args) {
        //直接通过类名访问静态变量,如果a声明名中的static删掉,此步会报错
        HelloJimmy.a = 20;
        //通过创建对象进行调用,不推荐这样使用
        HelloJimmy b = new HelloJimmy();
        b.a = 30;

        //通过类名直接访问静态方法,如果a声明名中的static删掉,此步会报错
        HelloJimmy.fun1();
        //通过创建对象访问
        b.fun1();
    }
}
静态变量

实例变量在每个实例中都有自己的一个独立“空间”,但是静态变量只有一个共享“空间”,所有实例都会共享该变量。对于静态变量,无论修改哪个实例的静态变量,效果都是一样的:所有实例的静态变量都被修改了,原因是静态变量并不属于实例。

package test;

public class TestOne {
    public static void main(String[] args) {
        HelloStatic a = new HelloStatic();
        HelloStatic b = new HelloStatic();
        a.setAge(20);//这步会同时改变b实例的age值
        System.out.println(a.getAge());//结果为20
        System.out.println(b.getAge());//结果也是20
    }
}

class HelloStatic {
    private static int age = 18;

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return this.age;
    }
}
静态方法

用static修饰的方法称为静态方法,跟静态变量一样,静态方法属于class而不属于实例,因此,静态方法内部,无法访问this变量,也无法访问实例字段,它只能访问静态字段。 需要的是,main()方法就是静态方法。

package test;

public class TestOne {
    private static int name;
    HelloStatic c=new HelloStatic();
    public static void main(String[] args) {
        System.out.println(this.name); 
        //报错:'test.TestOne.this' cannot be referenced from a static context
        System.out.println(c.getAge());
        //报错:Non-static field 'c' cannot be referenced from a static context
    }
}

class HelloStatic {
    private static int age;

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return this.age;
    }
}

静态方法如果要访问内部类,则该内部类需要加上static修饰符。

public class TestOne {
    public static void main(String[] args) {
        Person a = new Person();
        //报错:'test.TestOne.this' cannot be referenced from a static context
        //提示:make Person ‘static’
    }

    class Person {  //将Person这个内部类加上static修饰符即可被静态方法访问
        private int age;

        public void setAge(int age) {
            this.age = age;
        }

        public int getAge() {
            return this.age;
        }
    }
}

静态方法常用在工具类中,例如Math.random(); Arrays.sort();

package test;

class CompareM { //将CompareM作为一个比较大小的工具类
    //选取最大值
    public static int findMax(int a,int b){
        return a>b?a:b;
    }
    //选取最小值
    public static int findMin(int a,int b){
        return a>b?b:a;
    }
}

public class TestOne {
    public static void main(String[] args) {
        //下面使用工具类CompareM的静态方法
        System.out.println(CompareM.findMax(54,23));
        System.out.println(CompareM.findMin(3,744));
    }
}
静态变量和静态方法的设计思想

类属性(类变量)作为该类各个对象之间共享的变量。在设计类时,分析哪些类属性不因对象的不同而改变,将这些属性设置为类属性。相应的方法设置为类方法。

如果方法与调用者无关,则这样的方法通常被声明为类方法,由于不需要创建对象就可以调用类方法,从而简化了方法的调用。

接口的静态变量

接口里面可以存在常量,修饰符默认为public static final

public interface Test01{
    int a=10;//等同于public static final int a=10;
}

final非访问修饰符
  1. final修饰的类不能被继承。提高安全性,提高程序的可读性。
  2. final修饰的方法不能被子类重写。
  3. final修饰的变量(成员变量或者局部变量)即称为常量。变量名称通常用大写,且只能被赋值一次。
final修饰类
package test;

public final class Father{
    
}
class Son extends Father{
    //会报错:Cannot inherit from final 'test.Father',表示Father类不能被继承
}
final修饰方法
package test;

public class Father{
    public final String funFirst(){
        return "True";
    }
}
class Son extends Father{
    @Override
    public String funFirst() { //报错:'funFirst()' cannot override 'funFirst()' in 'test.Father'; overridden method is final,表示父类方法funFirst()不能被重写
        return super.funFirst();
    }
}
final修饰变量
package test;

public class Father{
    public final static int a=20;
}
class Son extends Father{
    public static void main(String[] args) {
        a=30;//报错:Cannot assign a value to final variable 'a',表示不能修改a的值
    }
}

final修饰的成员变量必须初始化值,可以直接赋值也可以在构造方法中赋初值(建议使用这种方式)。

public class Father{
    public final int a;//会报错:Variable 'a' might not have been initialized
}
package test;

public class Father{
    public final int a;//此处不能添加static,如果添加static必须通过直接赋值,不能用构造方法来赋初始值。final变量经常和static关键字一起使用,作为常量。
    public Father(int a){
        this.a=a;
    }
}
class Son extends Father{
    public Son(int a) { //必须显示调用super()方法
        super(a);
    }
}
class RunClass{
    public static void main(String[] args) {
        Son b=new Son(24);
        System.out.println(b.a); //输出24
        
        Father c=new Father(8);
        System.out.println(c.a);  //输出8
        
        c.a=23; //被构造方法赋了初始值,不能被修改,会报错:Cannot assign a value to final variable 'a'
    }
}

如果修饰的成员变量是一个引用类型,则是说这个引用的地址的值不能修改,但是这个引用所指向的对象里面的内容还是可以改变的。

posted @ 2020-08-29 07:10  Whatever_It_Takes  阅读(236)  评论(0编辑  收藏  举报