学习中遇到的问题——Java的<?>用法

在学习该项目时,遇到了<?>语法,不理解是什么意思,上网浏览后写总结以便复习。

public Predicate toPredicate(Root<MerchantsCarrier> root, CriteriaQuery<?> query,CriteriaBuilder criteriaBuilder)
<?>:如果想要使用?来做泛型。我们可以在写代码的时候不指定类型。也就是说,在使用类的时候不必确定这个泛型。

除此之外,还会遇到的情况是< T >

public interface GenericEntityRepository<T> extends GenericRepository<T, Long>

< T>:如果一个类中的方法、参数使用了T来做泛型,那么类上边也必须要写T泛型。也就是说如果使用了T来做泛型,就必须在使用这个类的时刻,确定这个泛型的类型。

总结:方法参数用T,则类中的参数也要写T;方法参数用?,则类中参数可以不写它。

### 编写一个方法来编译并加载 `.java` 文件为 `Class` 对象 在 Windows 环境下,可以通过调用 Java 的工具类和反射机制实现将 `.java` 文件动态编译并加载为 `Class` 对象的功能。以下是具体的方法描述以及其实现: #### 方法概述 为了完成这一目标,可以分为以下几个部分: 1. **创建临时目录**用于存储编译后的 `.class` 文件。 2. **执行编译命令**通过运行 `javac` 工具将源代码文件转换成字节码文件。 3. **自定义类加载器**以加载生成的 `.class` 文件。 --- #### 实现代码 以下是一个完整的解决方案: ```java import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.net.URL; import java.net.URLClassLoader; public class DynamicCompiler { public static Class<?> compileAndLoad(String sourceCode, String className) throws Exception { // Step 1: 创建临时目录保存.class文件 File baseDir = new File(System.getProperty("java.io.tmpdir"), "dynamic_classes"); if (!baseDir.exists()) { baseDir.mkdirs(); } // 定义输出路径 File outputDir = new File(baseDir, "output"); if (!outputDir.exists()) { outputDir.mkdirs(); // 使用Files.createDirectories替代也可以[^3] } // 将sourceCode写入.java文件 File javaFile = new File(outputDir, className + ".java"); try (FileWriter writer = new FileWriter(javaFile)) { writer.write(sourceCode); } // Step 2: 调用javac编译器进行编译 ProcessBuilder processBuilder = new ProcessBuilder( "javac", "-d", outputDir.getAbsolutePath(), javaFile.getAbsolutePath()); processBuilder.redirectErrorStream(true); Process process = processBuilder.start(); int exitCode = process.waitFor(); if (exitCode != 0) { throw new RuntimeException("Compilation failed."); } // Step 3: 自定义类加载器加载.class文件 URL url = outputDir.toURI().toURL(); URLClassLoader classLoader = new URLClassLoader(new URL[]{url}); return classLoader.loadClass(className); // 加载指定名称的类 } public static void main(String[] args) throws Exception { // 测试代码 String sourceCode = "public class HelloWorld {\n" + " public String greet() {\n" + " return \"Hello, World!\";\n" + " }\n" + "}"; Class<?> clazz = compileAndLoad(sourceCode, "HelloWorld"); Object instance = clazz.getDeclaredConstructor().newInstance(); System.out.println(clazz.getMethod("greet").invoke(instance)); // 输出 Hello, World! } } ``` --- #### 关键点解析 1. **完全限定名与内部形式** - 在 Java 中,当涉及到类的全限定名时,通常会使用点号分隔的形式(如 `java.lang.String`)。然而,在底层操作中(例如类加载器),可能会遇到斜杠分隔的形式(如 `java/lang/String`)[^1]。因此需要注意这两种表示方式之间的差异。 2. **字节码的作用** - 当 Java 源程序被编译后,它会被转化为一种中间语言——字节码(`.class` 文件)。这种字节码不依赖于具体的硬件平台,可以在任何支持 JVM 的设备上运行[^2]。 3. **类加载器的工作原理** - 类加载器负责将字节码文件加载到内存中,并将其转换为可供 JVM 执行的对象模型。上述代码中的 `URLClassLoader` 是标准库提供的一种灵活的类加载器实现。 4. **跨平台注意事项** - 上述代码适用于 Windows 平台,但在其他操作系统上可能需要调整路径分隔符或其他细节。不过由于 Java 提供了统一的 API 接口,大多数情况下无需额外修改即可正常工作。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值