java - 反射值未正确输出
问题描述
我目前正在做一个项目,我决定创建一个新的测试项目来了解我失败的地方。我以一种简单的方式重新创建了我正在使用的类。我的测试项目如下所示:
这些是 Java 类。
ChunkGenerator
package chunk;
public interface ChunkGenerator {
WorldChunkManager getManager();
}
ChunkGeneratorAbstact
package chunk;
public class ChunkGeneratorAbstract implements ChunkGenerator {
private WorldChunkManager c;
public ChunkGeneratorAbstract(WorldChunkManager c){
this.c = c;
}
@Override
public WorldChunkManager getManager() {
return c;
}
}
WorldChunkManager
package chunk;
import java.util.UUID;
public class WorldChunkManager {
private UUID uuid;
public WorldChunkManager(UUID uuid){
this.uuid = uuid;
}
public UUID getUuid() {
return uuid;
}
}
World
package world;
public class World {
private WorldProvider provider;
public World(WorldProvider provider){
this.provider = provider;
}
public WorldProvider getProvider(){
return provider;
}
}
Main
import chunk.ChunkGenerator;
import chunk.ChunkGeneratorAbstract;
import chunk.WorldChunkManager;
import world.World;
import world.WorldProvider;
import java.lang.reflect.Field;
import java.util.UUID;
public class Main {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
WorldChunkManager manager = new WorldChunkManager(UUID.randomUUID());
System.out.println("DEFAULT MANAGER UUID:" + manager.getUuid());
ChunkGeneratorAbstract chunkGeneratorAbstract = new ChunkGeneratorAbstract(manager);
System.out.println("ChunkGeneratorAbstract: " + chunkGeneratorAbstract.getManager());
ChunkGenerator generator = new ChunkGenerator() {
@Override
public WorldChunkManager getManager() {
return manager;
}
};
WorldProvider provider = new WorldProvider(generator);
System.out.println("DEFAULT PROVIDER: " + provider);
World world = new World(provider);
Field field = chunkGeneratorAbstract.getClass().getDeclaredField("c");
field.setAccessible(true);
WorldChunkManager manager1 = new WorldChunkManager(UUID.randomUUID());
field.set(chunkGeneratorAbstract, manager1);
System.out.println("CUSTOM MANAGER UUID: " + manager1.getUuid());
System.out.println("FINAL:" + world.getProvider().getGenerator().getManager().getUuid());
}
}
这是putput:
DEFAULT MANAGER UUID:7c85e3ec-2288-4427-aae3-ce9e0b72c581
ChunkGeneratorAbstract: chunk.WorldChunkManager@2b193f2d
DEFAULT PROVIDER: world.WorldProvider@355da254
CUSTOM MANAGER UUID: 98a89e86-3b81-4fc3-8b5d-f22645b1685a
FINAL:7c85e3ec-2288-4427-aae3-ce9e0b72c581
正如您在使用反射并将 设置WorldChunkManager
为自定义后看到的那样,我尝试打印出 的 UUID WorldChunkManager
,但由于某种原因,我一直得到原始的而不是自定义的
解决方案
ChunkGenerator
您在此代码中有 2 个实例:
// 1
ChunkGeneratorAbstract chunkGeneratorAbstract = new ChunkGeneratorAbstract(manager);
// 2
ChunkGenerator generator = new ChunkGenerator() {
@Override
public WorldChunkManager getManager() {
return manager; // hard-coded to return manager
}
};
您使用反射来更改WorldChunkManager
of chunkGeneratorAbstract
,但WorldProvider
创建时引用了另一个:
WorldProvider provider = new WorldProvider(generator);
// ^^^^^^^^^
World world = new World(provider);
当你这样做时world.getProvider().getGenerator()
,它会返回 other ChunkGenerator
,它被硬编码为 return manager
。
我想您需要创建WorldProvider
这种方式来查看您期望的行为:
WorldProvider provider = new WorldProvider(chunkGeneratorAbstract);
还:
这个问题实际上与反射的使用无关。如果你在
ChunkGeneratorAbstract
课堂上做了一个 setter 并使用它,你会看到同样的问题。像这样使用反射设置私有字段不是一个好习惯。我们将类(和其他成员)的字段设为私有,作为与使用该类的代码的合同的一部分。约定是使用该类的代码必须以某种方式使用它(由其设计者规定),并且不得依赖私有成员。通过使用反射来访问私有成员,您违反了该合同。
推荐阅读
- django - 如何通过按下按钮更新 Django 中的页面
- oracle - 无法在 Oracle SQL Developer v19.0.1 中创建 PRIVATE TEMPORARY TABLE(错误:ORA-00905)
- go - 我应该在哪里存储服务注册服务器的端点?
- angular - Array.push() 增加全局条目数量
- kubernetes - Kubernetes 已弃用的 SSH 隧道功能的替代方案是什么?
- sql - 如何在我的查询中使用 case 语句,以便在“NULL”或 0 的情况下,我将用 1 替换它们
- java - 东部时间 (ET) 的正确 ZoneId:“US/Eastern”还是“America/New_York”?
- r - Left_join by reference for data.table 的重复键
- angular - 如何创建 PUT 方法来更新用户
- html - 悬停文本覆盖上的奇怪文本阴影/双文本