我们在一些 ANT 构建文件中使用嵌入式 javascript 代码,并将 Nashorn 功能内置到 Java 8+ 中。在 Java 15 中,Nashorn 功能已被删除,因此我们使用独立的nashorn.jar文件对此进行了测试。我们刚刚添加:
<classpath> <pathelement location="<path>/nashorn.jar"/> </classpath>
一切进展顺利。对于 Java 16,这在构建 16+27 中运行良好。
当我运行一个简单的测试 ANT 脚本时,从 java 16+29(及更高版本)开始:
<project name="Test" default="build" basedir=".">
<target name="build">
<echo message="Begin"/>
<script language="javascript">
<classpath> <pathelement location="C:/nashorn/nashorn-0.1.0.2013070801.jar"/> </classpath>
print('Hello from embedded Javascript');
</script>
<echo message="End"/>
</target>
</project>
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
build.xml:5: java.lang.IllegalAccessError: class jdk.nashorn.internal.codegen.types.Type (in unnamed module @0xeafc191) cannot access class jdk.internal.org.objectweb.asm.Type (in module java.base) because module java.base does not export jdk.internal.org.objectweb.asm to unnamed module @0xeafc191 …Run Code Online (Sandbox Code Playgroud) 使用 JDK 16,我声明了两个注释:
@Target({ ElementType.RECORD_COMPONENT})
@Retention(RetentionPolicy.RUNTIME)
public @interface A {}
@Target({ ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface B {}
Run Code Online (Sandbox Code Playgroud)
我声明了一个像这样的记录类?
public record User(@A @B long id, String name, int age) {}
Run Code Online (Sandbox Code Playgroud)
然后我使用反射来获取id的注解,即:
Annotation[] annotations = fields[0].getAnnotations();
Run Code Online (Sandbox Code Playgroud)
但是 的大小annotations是 1 而我只有@B,这是为什么呢?谢谢
我在想这样的事情:
record Foo() implements Cloneable {
public Foo clone() {...}
}
Run Code Online (Sandbox Code Playgroud)
这是一件好事吗?我们应该避免它以支持未来的枯萎吗?
我有一个 Maven 项目。它是用 Java 16 编写的。我安装了 Java 16 JDK。
当我用 dockerfile 构建它时,一切正常,但是当我运行 docker 并继续我的项目 url 时,我得到了一个“不受支持的类文件主要版本 60”。
可以在 tomcat 或其他东西上运行 java 16 项目吗?
有我的一些文件:
Docker 文件:
FROM maven:3.8.1-openjdk-17 as builder
RUN mkdir -p /root/.m2 && mkdir /root/.m2/repository
COPY . /app/
RUN cd /app && mvn clean package -Dmaven.test.skip=true
FROM tomcat:9.0-jdk16-openjdk
COPY --from=builder /app/target/demo.war /usr/local/tomcat/webapps
ENV CATALINA_OPTS=""
EXPOSE 8080
CMD ["catalina.sh", "run"]
Run Code Online (Sandbox Code Playgroud)
还有我的 pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>demo</artifactId>
<packaging>war</packaging>
<version>0.0.1</version>
<name>demo</name>
<url>http://maven.apache.org</url>
<properties>
<!-- Dependencies properties --> …Run Code Online (Sandbox Code Playgroud) 发现collect(Collectors.toList())和Stream.toList()之间的区别。看
class Animal { }
class Cat extends Animal { }
record House(Cat cat) { }
class Stuff {
public static void function() {
List<House> houses = new ArrayList<>();
List<Animal> animals1 =
houses.stream()
.map(House::cat)
.collect(Collectors.toList()); // ok
List<Animal> animals2 =
houses.stream()
.map(House::cat).toList(); // compile error
List<Animal> animals3 =
houses.stream()
.map(House::cat)
.map(cat -> (Animal) cat).toList(); // ok
}
}
Run Code Online (Sandbox Code Playgroud)
collect(Collectors.toList()) 能够给我一个动物列表或猫列表。但是Stream.toList()只能给出Cat的List。
问题是有什么方法可以让 Stream.toList() 工作。在我的现实世界示例中,我有一个类覆盖 shutdownNow,它返回 Runnable 列表,因此我的类调用了 some.stream().collect(Collectors.toList()),但是 some.stream().toList()返回 MyRunnable 的列表。
我的一部分希望他们将函数声明为而default <U super T> List<U> toList()不是default List<T> …
我们总是可以在一个 .java 文件中有多个类。考虑到封装以及每个类都由多行代码组成,在 1 个 .java 文件中包含 1 个类(不要谈论嵌套类)总是有意义的。
现在记录开始发挥作用,它们可以少至 1 行代码。在同一个 .java 类中封装多个记录是否有意义?
例如我们可以有
DTO.java文件将包含
record Employees(List<Employee> employees) { } //This is just a wrapper class that we normally need in order to return a list of objects in rest web services
record Employee(String name, Integer age, List<Attribute> attributes){ }
record Attribute(String name, String value) { }
Run Code Online (Sandbox Code Playgroud)
如果没有记录具有公共访问修饰符,那么我们可以将所有记录包含在名为DTO.java的文件中
在我看来,拥有 3 个 .java 文件,每个文件中只有 1 行代码似乎不太好。
但是,我们仍然会面临类似这里描述的问题,即同一 java 文件中的多个类
为了在 JDK 15 中使用记录,我曾经使用--enable-preview --release 15在 Ant 构建上传递给 javac 的参数进行编译。一切都编译并运行良好。
使用 JDK 16 时,如果我使用相同的参数进行编译,我会得到
错误:带 --enable-preview 的源版本 15 无效(仅版本 16 支持预览语言功能)
记录是 JDK 16 的标准功能,因此我预计应该在没有这些参数的情况下进行编译。但是,如果我删除它们,我会得到
Foo.class 使用 Java SE 15 的预览功能。(使用 --enable-preview 允许加载包含预览功能的类文件)
Ant 报告编译失败:
编译失败;有关详细信息,请参阅编译器错误输出。在 org.apache.tools.ant.taskdefs.Javac.compile (Javac.java:1425)
因此,无论有没有标志,编译都会失败。怎么了?
我对使用新的 JDK 16 记录很感兴趣,但是当我尝试创建一个具有附加参数的新记录时,出现错误:
public record DrivePacket(Path drivePath, long driveSize) {
public DrivePacket(Path drivePath, long driveSize) {
this.drivePath = drivePath;
this.driveSize = driveSize;
}
public DrivePacket(Path drivePath, long driveSize, String ID) {
this(drivePath, driveSize);
this.id = id;
}
}
Run Code Online (Sandbox Code Playgroud)
记录仅用于没有任何可变性的对象,还是可以随时间扩展?
我对这种类型的类有一个新要求(特别是意外添加了 NFS 共享上的驱动器类型“远程”驱动器。
我发现自己试图想出一些方案,比如使用driveSize来指示“远程”状态,但实际上这就是开发枚举的原因。
在这种情况下我该怎么办?我可以向构造函数添加选项并将它们存储在私有 final 字段中吗?或者我应该创建一个DrivePacket->的子类RemoteDrivePacket,还是应该创建一个标记接口RemoteDrivePacket?
开发人员打算使用它的典型方式是什么?
我有一个有点不寻常的问题。我目前正在尝试在 Java 16 中编写一个用于处理不和谐的聊天过滤器。
\n在这里我遇到了一个问题,在德语中,有几种方法可以编写一个单词来绕过这个过滤器。
\n作为一个例子,我现在以侮辱“Hurensohn”为例。\n现在你可以简单地在聊天中写“Hur \xc3\xa4 nsohn”或“Hur 3 nsohn”,从而很容易地绕过过滤器。
\n由于我不想手动将所有可能性打包到过滤器中,所以我考虑了如何自动完成它。所以我做的第一件事是创建一个包含所有可能的替代字母的哈希图,它看起来像这样:
\nMap<String, List<String>> alternativeCharacters = new HashMap<>();\nalternativeCharacters.put( "E", List.of( "\xc3\xa4", "3" ) );\nRun Code Online (Sandbox Code Playgroud)\n我尝试更改单词中对应的字母并将其添加到聊天过滤器中,这确实有效。
\n但现在我们遇到了问题:\n为了能够覆盖所有可能的组合,仅更改单词中的一种类型的字母对我来说并没有多大好处。
\n如果我们现在取单词“Einschalter”并更改此处的字母“e”,我们也可以简单地将此处的“e”更改为“3”或“\xc3\xa4”,从而会出现以下结果:
\n和
\n但现在我也想创造“混合”词。例如“3inschal\xc3\xa4r”,其中“\xc3\x84”和“3”都用于创建单词。然后会出现以下组合:
\n有谁知道我怎样才能实现这样的事情?使用普通的 Replace() 方法,我还没有找到创建“混合”替换的方法。
\n我希望人们理解我有什么样的问题以及我想做什么。:D
\n目前用于替换的方法:
\n public static List<String> replace( String word, String from, String... to ) {\n\n …Run Code Online (Sandbox Code Playgroud) 你好,我是 java 新手,我使用的是 java 15。然后出现了更新版本的 java,它是 16。我下载了它并将其安装在我的计算机中。然后我发现可以使用java控制面板更新java。但我找不到它。谁能帮我?jdk-16中有Java控制面板吗?
我将以下遗留代码迁移到 Java 16,但是由于这个新版本引入了强封装,它不起作用:
try {
Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
method.setAccessible(true);
method.invoke(new URLClassLoader(
new URL[] {}),
new File("C:/external-folder/my.jar").toURI().toURL()
);
} catch (Exception exc) {
exc.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)
有办法让它发挥作用吗?
由于 Record 类实例没有公共 Object 实例所具有的 obj 头。但是我们仍然可以使用同步功能,例如:
public record User(long id, String name, int age) {}
User user = new User(1, "name", 18);
synchronized (user) {
user.wait();
System.out.println("test");
}
Run Code Online (Sandbox Code Playgroud)
从轻量级锁到重级锁的转换过程会不会像普通对象实例一样?
一个记录类自动获取许多标准成员:
- 对于头部中的每个组件,两个成员:一个与组件同名且返回类型相同的公共访问器方法,以及一个与组件类型相同的私有 final 字段;
如果生成的 final 字段与访问器方法具有相同的名称,为什么不生成公共 final 字段呢?
由于记录类的实例可以序列化和反序列化,因此记录组件几乎不会被小心地更改。但是,不能通过提供 writeObject、readObject、readObjectNoData、writeExternal 或 readExternal 方法来自定义流程
所以改变 API 内部实现(记录组件)不是一个合适的理由。但我从@Brian Goetz那里得到了充分的理由
谢谢大家关注我的傻问题
java ×13
java-16 ×13
java-record ×3
ant ×2
reflection ×2
class ×1
cloneable ×1
docker ×1
java-15 ×1
java-17 ×1
java-console ×1
javac ×1
javascript ×1
maven ×1
nashorn ×1
replace ×1
string ×1
tomcat ×1