阿药陪你学Java(第七讲:修饰符与关键字)

第七讲:修饰符与关键字

Java中修饰符分为访问控制修饰符和非访问控制修饰符两种,主要用于修饰类、属性、方法等,一般放在语句的最前端,修饰后面的语句进而达到某种目的;如访问控制、是否可修改等。

关键字不像修饰符一样其用于修饰类或属性等,它用于代指或判断等;如代替指当前对象调用方法、判断某个对象的类型等。

访问控制修饰符

可以使用访问控制符来保护对类、属性、方法和构造方法的访问。Java 支持 4 种不同的访问权限。

  • default (即默认,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
  • private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
  • public : 对所有类可见。使用对象:类、接口、变量、方法。
  • protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
修饰符当前类同一包内子孙类(同一包)子孙类(不同包)其他包
publicyesyesyesyesyes
protectedyesyesyesyes/nono
defaultyesyesyesnono
privateyesnononono

非访问控制修饰符

非访问控制修饰符的作用主要是让类、属性、方法等具有某种特殊的功能,不存在访问权限的限制。

  • static 修饰符,用来修饰类方法和类变量。
  • final 修饰符,用来修饰类、方法和变量,final 修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的。
  • abstract 修饰符,用来创建抽象类和抽象方法。
  • synchronizedvolatile 修饰符,主要用于线程的编程。

static修饰符

被static修饰变量和方法也被成为静态变量和静态方法,它们只属于类本身,无论这个根据这个类创建类多少个对象,静态属性和静态方法都只有一份,所有对象所共享。

注意

  1. 局部变量不能声明为static变量。
  2. 静态方法不能使用类的非静态变量,非静态方法可以使用静态变量。
示例:
class Demo {

    static int a = 10; // 静态变量

    int b = 10; // 非静态变量

    public static void main(String[] args) {
        Demo demo1 = new Demo(); // 创建第一个对象demo1
        demo1.a++; // 修改(类的)静态变量的值
        demo1.b++; // 修改(对象demo1)非静态变量的值
        System.out.println(demo1.a);
        System.out.println(demo1.b);

        Demo demo2 = new Demo(); // 创建第二个对象demo2
        demo2.a++; // 修改(类的)静态变量的值
        demo2.b++; // 修改(对象demo2)非静态变量的值
        System.out.println(demo2.a);
        System.out.println(demo2.b);
        
        staticMethod(); // 静态方法可以直接调用静态方法
        // method(); // 静态方法不可以直接调用非静态方法
        demo2.method(); // 通过对象可以在静态方法中调用非静态方法
    }

    public static void staticMethod() { // 静态方法
        System.out.println("a的值为:" + a); // 静态方法可以使用静态变量
        // System.out.println("b的值为:" + b); // 静态方法不可以使用非静态变量
    }

    public void method() { // 非静态方法
        System.out.println("a的值为:" + a); // 非静态方法可以使用静态变量
    }
}

输出:
11
11
12
11
a的值为:12
a的值为:12

final修饰符

final修饰的变量其实就是一个常量,一但赋值就不可改变。

示例:
class Demo {
    static final int a = 10;
    public static void main(String[] args) {
        // a = 20; // final修饰的变量是一个常量,值不可变
        System.out.println("a的值是:" + a);
    }
}

输出:
a的值是:10

final修饰的方法可以被子类继承,但是不能被子类重写。声明 final 方法的主要目的是防止该方法的内容被修改。

语法:
public final void method() {
   // 方法体
}

final修饰的类不能被继承,也就是说final修饰的类不会有子类。

语法:
public final class Demo {
   // 类体
}

abstract修饰符

abstract可以修饰类和方法,修饰的类是抽象类,修饰的方法是抽象方法。

注意

  1. 抽象方法只有声明,没有方法体,具体实现依靠子类实现。
  2. 抽象类和抽象方法不能被final修饰,因为需要子类继承抽象类并实现它的抽象方法。
  3. 抽象类不一定有抽象方法,但是有抽象方法的一定是抽象类。
  4. 抽象类不能用来创建对象。
语法:
abstract class Demo { // 抽象类
    abstract void test(); // 抽象方法
}

class SubClass extends Demo { // 子类继承抽象类
    void test() { // 实现抽象类中的抽象方法
        System.out.println("success");
    }
}

synchronized修饰符

synchronized修饰的变量或方法在同一时间只能被一个线程访问。(详情在多线程部分具体介绍)

注意

  1. synchronized可以修饰变量、方法、类、代码块等,使用范围较广。
  2. synchronized可以保证有序性、原子性、可见性。
  3. synchronized使用可能会造成线程阻塞。

volatile修饰符

volatile修饰的变量在每次被线程访问时,都强制从共享内存中重新读取该变量的值。而且,当变量的值发生变化时,会强制线程将变化值回写到共享内存。这样在任何时刻,不同的线程总是看到某个成员变量的同一个值。(详情在多线程部分具体介绍)

注意

  1. volatile只能修饰变量。
  2. volatile可以保证有序性、可见性,不能保证原子性。
  3. volatile使用不会造成线程阻塞。

this关键字

this可以代指当前对象,使用this可以调用该对象的属性和方法等。

示例:
class Demo {

    int a = 10;

    public Demo(int a) {
        System.out.println("this的值:" + this);
        this.a = a; // this调用当前对象的属性a接收构造参数中参数a的值
    }

    public static void main(String[] args) {
        Demo demo = new Demo(20); // 创建一个demo对象
        System.out.println("demo的值:" + demo);
        System.out.println(demo.a); // demo对象调用属性a,但是这里不可以用this.a
    }
}

输出:
this的值:com.study.test8.Demo@76ed5528
demo的值:com.study.test8.Demo@76ed5528
20

通过上面的示例可以发现,this的值和demo对象的值是一致的,所以this代指的其实就是创建的demo对象。

扩展

问:既然this代指的是demo对象,为什么 System.out.println(demo.a); // demo对象调用属性a,但是这里不可以用this.a ?

答:因为this只能在属于对象自己的方法内部使用,也就是可以在非静态方法内部使用;静态方法属于类而不属于某个对象,所以在静态方法中不能使用this。

instanceof关键字

在Java中,instanceof关键字是二进制运算符,它用于检查对象是否是特定类的实例。

语法:
result = objectName instanceof ClassName // result的值只能是true或false

示例:
class Demo {
    public static void main(String[] args) {
        Demo demo = new Demo();
        boolean result = false;
        if (result = demo instanceof Demo) { // 判断demo是否是Demo类的一个对象
            System.out.println("demo是Demo类的一个对象:" + result);
        } else {
            System.out.println("demo不是Demo类的一个对象:" + result);
        }
    }
}

输出:
demo是Demo类的一个对象:true

扩展

  1. 如果子类继承了父类,然后创建了一个子类对象,判断它是否是父类的一个对象?结果为:是。

  2. 如果类实现了一个接口,然后通过该类创建了一个对象,判断它是否是接口的一个对象?结果为:是。

示例:
class SubClass extends Demo {
    // 类体
}
class Demo {
    public static void main(String[] args) {
        SubClass subClass = new SubClass();
        if (subClass instanceof Demo) {
            System.out.println("是");
        } else {
            System.out.println("不是");
        }
    }
}

输出:
是

示例:
interface DemoInterface {
	// 接口体
}
class Demo implements DemoInterface {
    public static void main(String[] args) {
        Demo demo = new Demo();
        if (demo instanceof Demo) {
            System.out.println("是");
        } else {
            System.out.println("不是");
        }
    }
}

输出:
是
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值