Java的修饰符有哪几种
Java的修饰符有以下几种:
- 访问修饰符:public、protected、private和默认访问修饰符。
- 非访问修饰符:final、abstract、static、synchronized、volatile、transient、native、strictfp和@Deprecated。
什么是访问修饰符?
访问修饰符是指用于限定类、变量、方法等在其他类中的可见性的关键字,包括public、protected、private和默认访问修饰符(即不写访问修饰符时的默认访问级别)。访问修饰符的作用是控制类成员的访问权限,实现封装和信息隐藏,从而保证程序的安全性和可维护性。
那什么是非访问修饰符?
非访问修饰符是指用于修饰类、变量、方法等的关键字,除了访问修饰符以外的修饰符。Java中常用的非访问修饰符包括final、abstract、static、synchronized、volatile、transient、native、strictfp和@Deprecated注解等。这些修饰符可以用于控制类的继承、方法的实现方式、变量的存储方式等方面。
帮我举个可运行的访问修饰符的代码例子
当定义一个类、方法或变量时,可以使用四种不同的访问修饰符:public、protected、private和默认(没有任何关键字)。以下是一个简单的可运行的例子,演示了这四种访问修饰符的使用方式:
public class AccessModifierExample {
public String publicVariable = "This is a public variable";
protected String protectedVariable = "This is a protected variable";
private String privateVariable = "This is a private variable";
String defaultVariable = "This is a default variable";
public void publicMethod() {
System.out.println("This is a public method");
}
protected void protectedMethod() {
System.out.println("This is a protected method");
}
private void privateMethod() {
System.out.println("This is a private method");
}
void defaultMethod() {
System.out.println("This is a default method");
}
public static void main(String[] args) {
AccessModifierExample example = new AccessModifierExample();
System.out.println(example.publicVariable); // Output: This is a public variable
System.out.println(example.protectedVariable); // Output: This is a protected variable
System.out.println(example.privateVariable); // Compilation error
System.out.println(example.defaultVariable); // Output: This is a default variable
example.publicMethod(); // Output: This is a public method
example.protectedMethod(); // Output: This is a protected method
example.privateMethod(); // Compilation error
example.defaultMethod(); // Output: This is a default method
}
}
在这个例子中,我们定义了一个名为AccessModifierExample的类,并在其中定义了四个实例变量和四个实例方法,每个变量和方法都使用不同的访问修饰符。在main方法中,我们创建了一个AccessModifierExample对象,并尝试访问每个变量和方法。通过这个例子,可以清晰地看到每个访问修饰符的作用。
帮我举个可运行的非访问修饰符的代码例子
final
下面是一个使用final修饰符的代码示例:
public class FinalExample {
public static void main(String[] args) {
final int a = 10;
//a = 20; // 编译错误,因为a被final修饰,不能再次赋值
System.out.println("a的值是:" + a);
}
}
在这个例子中,我们使用final修饰符来声明一个常量a,并将其初始化为10。由于a被final修饰,所以在之后的代码中不能再对它进行修改。如果尝试修改a的值,就会导致编译错误。
abstract
- 解释:使用abstract修饰的类称为抽象类,使用abstract修饰的方法称为抽象方法。抽象类不能被实例化,只能被继承。抽象方法没有方法体,必须在子类中被重写。
- 示例代码:
public abstract class Animal {
private String name;
public Animal(String name) {
this.name = name;
}
public abstract void makeSound(); // 抽象方法
public void eat() {
System.out.println(name + "正在吃东西");
}
}
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
public void makeSound() {
System.out.println("汪汪汪");
}
}
public class Cat extends Animal {
public Cat(String name) {
super(name);
}
public void makeSound() {
System.out.println("喵喵喵");
}
}
public class Main {
public static void main(String[] args) {
Animal dog = new Dog("旺财");
Animal cat = new Cat("小花");
dog.makeSound(); // 汪汪汪
cat.makeSound(); // 喵喵喵
}
}
在这个例子中,我们定义了一个抽象类Animal,并声明了一个抽象方法makeSound()。我们不能直接实例化Animal类,只能通过继承它的子类来创建对象。在子类中,必须实现父类中的抽象方法makeSound()。
static
- 解释:使用static修饰的变量和方法称为静态变量和静态方法。静态变量和静态方法不依赖于任何对象,可以直接通过类名调用。静态变量在类加载时会被初始化,而不是在对象创建时。静态方法不能访问非静态成员,因为它们不依赖于任何对象。
- 示例代码:
public class Counter {
private static int count = 0; // 静态变量
public Counter() {
count++;
}
public static int getCount() { // 静态方法
return count;
}
}
public class Main {
public static void main(String[] args) {
Counter c1 = new Counter();
Counter c2 = new Counter();
Counter c3 = new Counter();
System.out.println("对象数量:" + Counter.getCount()); // 对象数量:3
}
}
synchronized
synchronized
是Java中的关键字,它用于在多线程环境中同步访问方法或代码块,以保证线程安全。
具体地说,当一个方法或代码块用synchronized
修饰时,只有一个线程能够进入该方法或代码块执行,其他线程需要等待当前线程执行完成后才能进入。
下面是一个使用synchronized
的例子:
public class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized void decrement() {
count--;
}
public synchronized int getCount() {
return count;
}
}
在上面的例子中,increment
、decrement
和getCount
方法都被用synchronized
修饰,这保证了多个线程在访问这些方法时的互斥性。
volatile
volatile
是Java中的关键字,它用于保证变量的可见性和禁止指令重排,从而保证多线程环境下变量的正确性。
具体地说,当一个变量用volatile
修饰时,它会在每次被访问时都从主存中读取最新的值,而不是使用本地缓存的值。另外,volatile
还可以保证变量的写操作不会被重排到读操作之后,从而保证多线程环境下的正确性。
下面是一个使用volatile
的例子:
public class Counter {
private volatile int count = 0;
public void increment() {
count++;
}
public void decrement() {
count--;
}
public int getCount() {
return count;
}
}
在上面的例子中,count
被用volatile
修饰,这保证了多个线程在访问count
时都从主存中读取最新的值。
transient
transient
是Java中的关键字,它用于标记一个字段不需要被序列化。
具体地说,当一个字段用transient
修饰时,它会在对象被序列化时被忽略,也就是说,它的值不会被保存到序列化数据中。
下面是一个使用transient
的例子:
public class Person implements Serializable {
private String name;
private transient int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// getters and setters
}
native修饰符
native
是用来标识方法的,表示该方法的实现是由本地代码实现的,而不是在Java代码中实现的。被native修饰的方法可以被称为本地方法,它们是使用其他语言(如C和C++)编写的,然后通过Java Native Interface(JNI)与Java代码进行交互。
下面是一个示例:
public class NativeExample {
public native void sayHello();
static {
System.loadLibrary("NativeExample");
}
public static void main(String[] args) {
new NativeExample().sayHello();
}
}
这个示例定义了一个NativeExample
类,并在其中声明了一个native
方法sayHello()
。sayHello()
方法没有具体的实现,因为它的实现是在本地代码中定义的。static
代码块用于加载本地库,确保在使用本地方法之前可以访问它。main()
方法创建了一个新的NativeExample
对象,并调用了sayHello()
方法。
strictfp修饰符
strictfp
是一个关键字,用于确保浮点计算的精确性。当一个类、接口或方法使用strictfp
修饰符时,所有浮点计算都按照IEEE 754规范进行,无论平台和JVM版本如何。这可以确保在不同平台上的结果都是一致的。
下面是一个示例:
public strictfp class StrictfpExample {
private double d = 3.14159265358979323846;
public strictfp double calculate() {
return d * 2;
}
}
这个示例定义了一个StrictfpExample
类,并将其标记为strictfp
。calculate()
方法也被标记为strictfp
,确保在浮点计算中使用的规范是IEEE 754规范。d
字段存储了一个双精度浮点数的值,它在calculate()
方法中被使用。由于使用了strictfp
,所以在任何平台上计算的结果都将是一致的。
@Deprecated注解
@Deprecated
注解用于标识某个类、接口、方法或字段已经过时,不再建议使用。在使用已过时的API时,编译器会发出警告,提示开发人员应该考虑使用其他API。
下面是一个示例:
public class DeprecatedExample {
@Deprecated
public void oldMethod() {
// ...
}
public void newMethod() {
// ...
}
}
这个示例定义了一个DeprecatedExample
类,并在其中声明了一个已过时的oldMethod()
方法和一个新的newMethod()
方法。oldMethod()
方法被标记为已过时,编译器在使用它时会发出警告。开发人员应该尽可能使用newMethod()
方法