所以我有一个接口MyInterface<T>
有一个方法String save(T obj)
实现类有这个定义Animal<T> implements MyInterface<T>
。我的主要功能如下所示:
MyInterface<Cow> animal = new Animal<Cow>();
Cow cow = new Cow();
cow.setName("Rose");
animal.save(cow);
到目前为止,animal.save()
只能保存类型安全的奶牛。
现在问题。在我的Animal类中,我有save方法,但在我保存之前我想知道我的Cow有一个名字。 Cow类有getName()
方法。
保存方法:
@Override
public void save(T obj)
什么是从T obj
到Cow-object的合适方式,所以我可以使用成员方法getName()
?
我的想法是:
@Override
public void save(T obj)
{
Object unknown = obj.getClass().newInstance();
if (unknown instanceof Cow)
{
String name = ((Cow) unknown).getName();
}
}
这是“好”的java吗?我想我可以使用反射并搜索与unknown
对象相关的所有方法。
更新只要我定义MyInterface<Cow> animal = new Animal<Cow>();
就像这样我是安全的,但问题出现时它看起来像这样:
MyInterface<Object> animal = new Animal<Object>();
然后没有getName()
方法....
应尽可能避免使用instanceof
,因此应该反思。
我会添加一个单独的界面,指示某些东西是否处于可保存状态。然后,您的Animal
类需要将其泛型类型参数更改为仅允许可保存的项目。
interface Saveable
{
boolean canSave();
}
public class Cow implements Saveable
{
//...
@Override
boolean canSave()
{
return getName() != null && !getName().isEmpty();
}
}
public class Animal<T extends Saveable> implements MyInterface<T>
{
@Override
public void save(T obj)
{
if (obj.canSave())
{
//whatever
}
}
}
如果您假设所有动物都有名称,那么创建一个界面。
static interface HasName {
String getName();
}
然后,所有具有名称的对象都应实现该接口
class Cow implements HasName{
String name;
Cow(String name){
this.name = name;
}
@Override
public String getName() {
return name;
}
}
然后修改Annimal
以允许实现接口的所有对象,您将能够获得它们的名称:
class Annimal<T extends HasName> {
void save(T obj) {
...
String name = obj.getName();
}
}
即使使用instanceof
,就像在你的帖子中一样,这是一种避免的做法,因为如果有一天你想要实现一种新型动物,让我们说Horse
,你将不得不修改你的保存方法的实现来添加if (unknown instanceof Horse)
条件。
不,这是“不行”的Java。首先是因为你想要避免向下倾斜,但主要是因为你想要使用这样的反射。
如果getName()
功能确实是您模型的重要组成部分,那么请考虑将其放置在自己的界面中。
意思是:如果有的话,你应该做的事情
@Override
public void save(T obj) {
if (obj instanceof NamedThingy) {
then cast ...
所有答案都很棒,可以毫无疑问地使用。但我仍有一些建议。虽然其他人大部分时间都在谈论一个新界面,然后调用像getName()
或canSave
这样的方法(它确实像魅力一样),我更喜欢使用自定义测试器,如Predicate<T>
。
我假设您的MyInterface
就像一个将实体保存到数据库或类似数据结构的服务。然后你可以调整你的类Animal
如下:
public class Animal<T> implements MyInterface<T>{
private final Predicate<T> canSave;
public Animal(Predicate<T> canSave){
this.canSave = canSave;
}
@Override
public void save(T obj){
if(canSave.test(obj)){
// your save logic
}
}
}
这样,您可以在保存该实体时为每个Animal
实例定义一个行为:
Animal<Cow> animal = new Animal<>(c -> c.getName() != null); // save only when name not null
Cow cow = new Cow();
animal.save(cow); // doesn't save because name is null
cow.setName("Rose");
animal.save(cow); // saves because name is set
animal = new Animal<>(c -> true); // save always
cow.setName(null);
animal.save(cow); // saves because it can always