Java中的Classpath是什么以及如何安装它?
来源:Medium 了解编程基础知识和程序文件的执行流程有助于我们理解一门语言。了解Classpath参数是每个Java开发人员都应该了解的基本概念之一。今天我们将讨论什么是类路径(Classpath)、如何设置它以及它如何帮助 JVM 执行类文件。什么是类路径?
类路径是Java中的基本参数之一,但它经常被编程新手误解。简单来说,类路径只是一组路径,Java 编译器和 JVM 必须沿着这些路径找到编译或执行其他类所需的类。Classpath 如何帮助 JVM 执行类文件
让我们从一个例子开始。假设我们有一个Main.java文件,位于/Users/vikram/Documents/test-java/src/com/programming/v1/Main.java文件夹中。package com.programming.v1;
public class Main {
public static void main(String[] args) {
System.out.println("Hello classpath");
}
}
假设我们位于/Users/vikram/Documents中并且想要编译此类:
javac test-java/src/com/programming/v1/Main.java
现在,要执行这个类文件,我们需要使用类路径或java命令中的cp标志 告诉 Java 虚拟机在哪里查找.class文件。
vg@lp1 Documents % java -cp "test-java/src" com.programming.v1.Main
Hello classpath
vg@lp1 Documents % java -classpath "test-java/src" com.programming.v1.Main
Hello classpath
第一个参数是写入包的根文件夹。第二个参数是包名和类名。当执行Java命令时,Java虚拟机会查找test-java/src文件夹,然后加载主类来执行它。
如何设置类路径变量
在 Linux 机器上,可以按如下所示设置 Classpath变量:export CLASSPATH="test-java/src"
可以使用环境变量添加/更新 Windows 计算机上的类路径。 设置好环境变量后,就可以执行java命令了,如下所示:
vg@lp1 Documents % java com.programming.v1.Main
Hello classpath
这就是关于Classpath 的 全部信息。感谢您的阅读!
Java 中的不变性
来源:Medium Java 中的变量有两种类型:原始变量和引用变量。Java 中的所有内容都是按值传递的,但在引用类型的情况下,可以使用传递的内存地址来更新源数据。 Final关键字用于使变量充当常量,即避免重新赋值。这对于没有堆内存的基元非常有效,而对于引用类型,仅重新分配受到限制并且内部状态可以更改。这可能会导致许多并发问题和竞争条件。因此,在 Java 的常规类型中包含不可变特性提供了许多好处。Java 中不变性的好处
1. 线程安全
不可变类型不受多线程环境中竞争条件的影响,因为对象在创建后将保持一致。多个线程无法更改其内部状态,因此不需要同步。2. 基本型
Java 标准库中的String是基类的一个很好的例子。这是一个非常简单且不可变的类,可用于在其之上构建业务逻辑域。同样,不可变类型可以作为构建的基础类型。特征
1. Private 和 Final 字段
包含对象状态的字段是private和Final。私有可见性可防止直接访问该字段,而最终可见性可确保该字段仅分配一次。2.无修饰方法
私有字段不能在类外部访问。通常,分别提供访问方法(getter)和修饰符方法(setter)来读取和写入字段。为了确保一致性,不允许使用修饰符。3.最后一堂课
允许类继承可能会破坏不变性。扩展不可变类的子类可以影响对象的状态。因此,该课程是最终的。4. 防御性副本
在对象创建期间,不是将构造函数中的参数直接分配给私有字段,而是创建参数的深层副本(或不可变副本)将提供外部修改。如果参数之一是引用类型,则可以在调用方端轻松对其进行操作。创建保护副本可以让您避免这种操作。类似地,对于访问器(getters),不是直接引用内部字段,而是可以自由共享它的副本。执行
员工
import java.time.LocalDate;
import java.util.List;
import static java.util.List.copyOf;
public final class Employee {
private final long id;
private final String name;
private final LocalDate joinDate;
private final List<String> achievements;
public Employee(long id,
String name,
LocalDate joinDate,
List<String> achievements) {
this.id = id;
this.name = name;
this.joinDate = joinDate;
this.achievements = copyOf(achievements);
}
public long getId() {
return id;
}
public String getName() {
return name;
}
public LocalDate getJoinDate() {
return joinDate;
}
public List<String> getAchievements() {
return achievements;
}
}
-
并非所有字段在构造函数中都有保护副本。这是因为id是原始类型,而name和joinDate字段是不可变类型。它们不能被调用者更改并且将保持不变,而成就字段需要使用List.copyOf方法创建的参数的副本。这是因为copyOf返回一个不可变的List。
-
同样,访问器方法直接返回字段而不是防御性副本,因为所有字段类型都是不可变的(包括成就),因此不能在类外部进行修改。
改进
Java 16 之前
可以使用Lombok等库来改进Employee实现。这减少了代码的冗长并帮助它看起来更干净。该库附带注释以缩短标准代码。@Value(注释)可用于为所有参数创建 getter 和构造函数。这还创建了一个最终类以及私有和最终字段。需要注意的是,它还生成toString、equals和hashCode方法。可以使用@Value重写Employee实现,如下所示:import lombok.Value;
import java.time.LocalDate;
import java.util.List;
import static java.util.List.copyOf;
@Value
public class Employee {
long id;
String name;
LocalDate joinDate;
List<String> achievements;
public Employee(long id,
String name,
LocalDate joinDate,
List<String> achievements) {
this.id = id;
this.name = name;
this.joinDate = joinDate;
this.achievements = copyOf(achievements);
}
}
Java 16 及更高版本
Java 16 版本引入了新的Record函数。这些(如 JEP 所述)是充当不可变数据的透明载体的类,并且可以被视为名义元组。Employee类可以重新实现为记录 Employee,如下所示。import java.time.LocalDate;
import java.util.List;
import static java.util.List.copyOf;
public record Employee(long id,
String name,
LocalDate joinDate,
List<String> achievements) {
public Employee(long id,
String name,
LocalDate joinDate,
List<String> achievements) {
this.id = id;
this.name = name;
this.joinDate = joinDate;
this.achievements = copyOf(achievements);
}
}
GO TO FULL VERSION