Java 修饰符
Java 修饰符 用于控制类、属性、方法和构造函数的访问权限和行为。它们可以分为两组:
- 访问修饰符:
-
public: 意味着代码对所有类可访问。
-
private: 意味着代码只能在声明的类内部访问。
-
default: 意味着代码只能在同一包中访问。
-
protected: 意味着代码在同一包和子类中可访问。
- 非访问修饰符:
-
final: 意味着类不能被继承,属性和方法不能被重写。
-
static: 意味着属性和方法属于类,而不属于对象。
-
abstract: 意味着类不能用于创建对象,方法没有主体,必须由子类提供。
-
transient: 意味着在序列化包含它们的对象时,属性和方法将被跳过。
-
synchronized: 意味着方法一次只能由一个线程访问。
-
volatile: 意味着属性的值不会在本地线程缓存,总是从"主内存"读取。
示例:
访问修饰符:
// public类可以被任何类访问
public class Main {
// private属性只能在 Main 类内部访问
private int x = 10;
// default方法只能在同一个包中访问
void myMethod() {
System.out.println("This is a default method.");
}
// protected方法可以在同一个包和子类中访问
protected void myProtectedMethod() {
System.out.println("This is a protected method.");
}
public static void main(String[] args) {
Main myObj = new Main();
System.out.println(myObj.x); // 错误,无法访问私有属性
myObj.myMethod(); // 可以访问 default 方法
myObj.myProtectedMethod(); // 可以访问 protected 方法
}
}
非访问修饰符:
public class Main {
// final属性不能被修改
final int y = 20;
// static方法可以在不创建对象的情况下访问
static void myStaticMethod() {
System.out.println("This is a static method.");
}
// abstract方法没有主体,必须由子类提供
abstract void myAbstractMethod();
public static void main(String[] args) {
// y = 30; // 错误,无法修改 final 属性
myStaticMethod(); // 可以访问 static 方法
// myAbstractMethod(); // 错误,无法直接调用抽象方法
}
}
// 子类继承 Main 类并提供抽象方法的主体
class Child extends Main {
@Override
void myAbstractMethod() {
System.out.println("This is the implementation of myAbstractMethod.");
}
}
一些额外的说明:
-
可以使用多个修饰符来修饰类、属性、方法和构造函数。例如,
public final
表示类是公开的并且不能被继承。 -
修饰符是 Java 语言的重要组成部分,它们可以帮助您控制代码的访问权限和行为。
以下是一些有关 Java 修饰符的其他重要信息:
-
default 修饰符 也可以称为 package-private 修饰符。
-
protected 修饰符允许子类访问父类中的成员,但不允许外部类访问。
-
static 变量和方法也称为 类变量 和 类方法。
-
abstract 类不能被实例化,只能被继承。
-
transient 变量不会被序列化。
-
synchronized 方法可以防止多个线程同时执行。
-
volatile 变量保证每次读取都将获取最新的值。
Java 封装
封装 的含义是确保敏感数据对用户隐藏。为了实现这一点,你需要:
-
将类变量/属性声明为私有
-
提供公共的 get 和 set 方法以访问和更新私有变量的值
Get 和 Set 方法
私有变量只能在同一类中访问(外部类无法访问)。但是,如果我们提供了公共的 get 和 set 方法,就可以访问它们。
get 方法 返回变量值,而 set 方法 设置值。
两者的语法是它们都以 get 或 set 开头,后面跟着变量的名称,首字母大写:
public class Person {
private String name; // private = 受限制的访问
// Getter
public String getName() {
return name;
}
// Setter
public void setName(String newName) {
this.name = newName;
}
}
示例解释
-
get 方法返回变量 name 的值。
-
set 方法接受一个参数(newName)并将其分配给 name 变量。关键字 this 用于引用当前对象。
然而,由于 name 变量被声明为私有,我们无法从此类外部访问它:
public class Main {
public static void main(String[] args) {
Person myObj = new Person();
myObj.name = "John"; // 错误
System.out.println(myObj.name); // 错误
}
}
如果变量被声明为 public,我们期望以下输出:
John
然而,由于我们尝试访问一个私有变量,我们得到一个错误:
MyClass.java:4: error: name has private access in Person
myObj.name = "John";
^
MyClass.java
:5: error: name has private access in Person
System.out.println(myObj.name);
^
2 errors
相反,我们使用 getName() 和 setName() 方法来访问和更新变量:
public class Main {
public static void main(String[] args) {
Person myObj = new Person();
myObj.setName("John"); // 将 name 变量的值设置为 "John"
System.out.println(myObj.getName());
}
}
// 输出 "John"
为什么封装?
-
更好地控制类的属性和方法
-
类属性可以被设置为只读(如果仅使用 get 方法)或只写(如果仅使用 set 方法)
-
灵活性:程序员可以更改代码的一部分而不影响其他部分
-
数据的安全性增加
封装的优点:
-
提高安全性:隐藏内部实现细节,防止意外修改或访问敏感数据。
-
提高代码的模块化:将代码组织成独立的模块,每个模块只暴露必要的接口。
-
提高代码的可重用性:封装的模块可以被其他代码重用,降低代码的重复性。
-
提高代码的维护性:易于理解和维护代码,降低代码的复杂度。
一些额外的说明:
-
可以使用多个修饰符来修饰 get 和 set 方法,例如 public、protected 和 private。
-
可以使用 final 修饰符来声明常量,常量不能被修改。
-
可以使用 static 修饰符来声明静态方法和变量,静态方法和变量属于类,而不是对象。