Hefery 的个人网站

Hefery's Personal Website

Contact:hefery@126.com
  menu
73 文章
0 浏览
1 当前访客
ღゝ◡╹)ノ❤️

Java基础—修饰符

访问控制修饰符

在Java中提供了四种访问权限,使用不同的访问权限修饰符修饰时,被修饰的内容会有不同的访问权限

  • public:公共的
  • protected:受保护的
  • default:默认的
  • private:私有的
修饰符当前类同包子类其他包
publicYYYY
protectedYYY
defaultYY
privateY

编写代码时,如果没有特殊的考虑,建议这样使用权限:

  • 成员变量使用 private ,隐藏细节
  • 构造方法使用 public ,方便创建对象
  • 成员方法使用 public ,方便调用方法

主函数public static void main(String[] args)解析

  1. public:公共的意思,是最大权限修饰符
  2. static:由于 JVM 调用 main 方法的时候,没有创建对象(只能通过类名调用。main必须用static修饰)
  3. void:由于main方法是被 JVM 调用,不需要返回值
  4. main:主要的意思,所以 JVM 采用了这个名字作为程序的入口
  5. String[]:字符串数组
  6. args:数组名(在运行的时候,通过 Java 命令给 args 数组赋值)

静态-static

静态基本介绍

静态:该区域中的数据在整个程序运行期间一直占用这些存储空间,也可认为是其内存地址不变,直到整个程序运行结束

特点:

  • 随着类的加载而加载
  • 优先于对象存在
  • 对所有对象共享
  • 可以被类名直接调用

优点:

  • 对对象的共享数据进行单独空间的存储,节省内存,没有必要每个对象都存储一份
  • 可直接被类名调用

缺点:

  • 生命周期过长,随着类的消失而消失
  • 访问出现权限,即静态虽好但只能访问静态

静态存在形式

静态变量

  • 调用:访问类变量;类名.类变量名;
  • 特点:
    • 实例字段在每个实例中都有自己的一个独立“空间”,但静态字段只有一个共享“空间”,所有实例都会共享该字段
    • 所有的全局变量都是静态变量,而局部变量只有定义时加上类型修饰符static,才为局部静态变量
    • 局部静态变量占用内存时间较长,并且可读性差,因此,除非必要,尽量避免使用局部静态变量
内存分配生存周期调用方式共享方式访问方式
实例变量需要被实例化后才会分配内存取决于实例化的类的存在周期当该变量所在的类被实例化后,可通过实例名直接访问局部变量,不共享可以访问静态成员
静态变量在应用程序初始化时,存在内存当中,直到它所在的类的程序运行结束时才消亡应用程序的存在周期只能通过“类.静态变量名”调用,类的实例不能调用全局变量,被所有类的实例对象共享,即一个实例的改变了静态变量的值,其他同类的实例读到的就是变化后的值不能访问非静态成员

阐述静态变量和实例变量的区别?

  • 静态变量: static修饰的变量(类变量),属于类不属于类的任何一个对象,类不管创建多少个对象,静态变量在内存中有且仅有一个拷贝
  • 实例变量: 必须依存于某一实例,需要先创建对象然后通过对象才能访问到它。静态变量可以实现让多个对象共享内存

静态方法

  • 调用:static 修饰成员方法时,该方法称为类方法。静态方法在声明中有 static,使用类名来调用,而不需要创建类的对象类名.静态方法名(参数);

  • 格式:

    权限修饰符 static 返回值类型 方法名 (参数列表){  
    	// 执行语句 
    }
    
  • 特点

    • 调用实例方法必须通过一个实例变量,而调用静态方法则不需要实例变量,通过类名就可以调用因为静态方法属于 Class 而不属于实例。因此,静态方法内部,无法访问this变量,也无法访问普通成员变量或成员方法,静态方法可以直接访问静态变量和静态方法
    • 静态方法不能直接访问普通成员变量或成员方法;成员方法可以直接访问类变量或静态方法
    • 静态方法经常用于工具类。例如:Arrays.sort()、Math.random()

静态代码块

  • 位置:类中方法外
  • 执行:随着类的加载而执行且执行一次,优先于main方法和构造方法的执行
    • 格式:
      public class ClassName{   
      	static {     
      		// 执行语句    
      	} 
      }
      
  • 特点:
    • 随着类的加载而执行,只执行一次,并优先于 main 函数,静态代码块是由类调用的。类调用时,先执行静态代码块,然后才执行主函数态代码块其实就是给类初始化的,而构造代码块是给对象初始化的(静态代码块--构造代码块--构造方法)
    • 静态代码块中的变量是局部变量,与普通函数中的局部变量性质没有区别
    • 一个类中可以有多个静态代码块

不可变-final

子类可以在父类的基础上改写父类内容,比如,方法重写。那么我们能不能随意的继承 API 中提供的类,改写其内容呢?显然这是不合适的。为了避免这种随意改写的情况,Java 提供了 final 关键字,用于修饰不可改变内容

final:不可改变。可以用于修饰类、方法和变量

  • 类:被修饰的类,不能被继承
    final class 类名 {    
     	//方法体
    }
    
  • 方法:被修饰的方法,不能被重写,必须被赋值即常量
    权限修饰符 final 返回值类型 方法名(参数列表){     
    	//方法体 
    }
    
  • 变量:
    基本数据类型变量:被修饰的变量,不能被重新赋值
    引用类型的变量:初始化之后便不能再让其指向另一对象,即内存地址不能再更改。但不影响对象内部的成员变量值的修改

特点:

  • 当用 final 修饰⼀个类时,表明这个类不能被继承。final类中的所有成员方法都会被隐式地指定为 final
  • 对于⼀个 final 变量,如果是基本数据类型的变量,则其数值⼀旦在初始化之后便不能更改
    如果是引⽤类型的变量,则在对其初始化之后便不能再让其指向另⼀个对象

使用 final 的原因:

  • 锁定,以防任何继承类修改它的含义
  • 效率。在早期 Java 实现版本中,会将 final 方法转为内嵌调用

final 修饰基本数据类型变量不能再赋值

public class finalDemo {
    public static void main(String[] args) {
        //final修饰变量
        final int a = 10;
        //再赋值,报错(已分配assigned,不可再赋值)
        //a = 20;
    }
}
public class finalDemo {
    public static void main(String[] args) {
        // final修饰变量
        final int a = 10;
        for (int i = 0; i < 10; i++) {
            a = i;
            System.out.print(a + "、");
        }

	// 每循环一次,都是一个新变量
        for (int i = 0; i < 10; i++) {
            final int a = i;
            System.out.print(a + "、");
        }
    }
}

final 修饰引用类型的变量:初始化之后便不能再让其指向另一对象,但不影响对象内部的成员变量值的修改

public class finalDemo {
    public static void main(String[] args) {
        final Student student1 = new Student("张三",21);
        Student student2 = new Student("李四",12);

        // student1 = student2;  // 报错
        student2 = student1;

        student1.setAge(100);
        System.out.println(student1.getAge());  //100
    }
}

抽象-abstract

同步锁-synchronized

synchronized 声明的方法同一时间只能被一个线程访问。synchronized 修饰符可以应用于四个访问修饰符

格式:

public synchronized void showDetails(){
	.......
}

volatile

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

public class MyRunnable implements Runnable {
    private volatile boolean active;
    public void run() {
        active = true;
        while (active) {  // 第一行
            // 代码
        }
    }
    public void stop() {
        active = false; // 第二行
    }
}

通常情况下,在一个线程调用 run() 方法(在 Runnable 开启的线程),在另一个线程调用 stop() 方法。
如果第一行中缓冲区的 active 值被使用,那么在第二行的 active 值为 false 时循环不会停止。但是以上代码中我们使用了 volatile 修饰 active,所以该循环会停止


标题:Java基础—修饰符
作者:Hefery
地址:http://hefery.icu/articles/2022/02/14/1644832911174.html