我正在尝试从返回的对象GetDatbaseName()
访问方法obj
,但它返回错误,表明该方法不可用。
但是,当我对obj
进行类型转换时,它正在运行。
String name = ((Oracle)obj).GetDatabaseName();
如何处理这种通用?就像我可以为Oracle
和MongoDB
这样的每种返回类型进行类型转换。还有更好的实现吗?
// one class needs to have a main() method
public class HelloWorld
{
// arguments are passed using the text field below this editor
public static void main(String[] args)
{
Data dt = new Data("Oracle");
Object obj = dt.GetObject();
String name = obj.GetDatabaseName();
System.out.println(name);
}
}
public class Data
{
public String _type;
public Data(String type)
{
_type = type;
}
public Object GetObject()
{
Object obj = null;
switch(_type)
{
case("Oracle"):
obj = new Oracle("Test");
break;
case("MongoDB"):
obj = new MongoDB("TestCollection");
break;
}
return obj;
}
}
public class Oracle
{
public String _databaseName;
public Oracle(String databaseName)
{
_databaseName = databaseName;
}
public String GetDatabaseName() { return _databaseName; }
}
public class MongoDB
{
public String _collectionName;
public MongoDB(String collectionName)
{
_collectionName = collectionName;
}
public String GetCollectionName() { return _collectionName; }
}
答案 0 :(得分:1)
您的问题在以下几行:
Object obj = dt.GetObject();
String name = obj.GetDatabaseName();
就这些行而言,obj是Object类型,它没有被调用的方法;因此,这个问题。这是因为Java是强类型的。
要解决此问题,您需要具有此方法的类型,或使用反射。要使用具有此方法的类型,他们需要从公共父接口继承它,从公共接口实现它。你也可以包装你的对象或其他一些替代品。
在您的情况下,似乎常见的界面是最简单的方法。在这种情况下,每个类都应实现此接口,而不是使用Object,您的引用将是该接口的类型。
public Object GetObject()
会变成
public MyInterface GetObject()
和
public class Oracle
将是
public class Oracle implements MyInterface
MyInterface将声明方法
public interface MyInterface {
String GetDatabaseName();
}
注意Java约定,方法应该以小写
开头public interface MyInterface {
String getDatabaseName();
}
如果您无法更改代码以实现这些方法,则可以使用" instanceof"测试类类型。
name = (obj instanceof Oracle)?((Oracle)obj).GetDatabaseName():((MongoDB )obj).getCollectionName();
答案 1 :(得分:1)
有两种方法可以解决这个问题,第一种方法是使用通用class
,而第二种方法是使用interface
,如果您知道类具有相同的方法,第二种方法会更好,而通用的方法是如果类有不同的方法
public class DBtest{
public static void main(String[] args){
DataBase<Oracle> database = new DataBase<>(Oracle.class);
Oracle oracle = database.getDataBase();
System.out.println(oracle.getDatabaseName());
}
}
class DataBase<T>{
private T database;
public DataBase(Class<T> classOfT){
try {
database = classOfT.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public T getDataBase(){
return database;
}
}
class Oracle{
private String _databaseName;
public Oracle(){
_databaseName = "test";
}
public String getDatabaseName() { return _databaseName; }
}
正如您所看到的,无法定义数据库的名称,您可以编写<T extends Name>
这是一个具有getName()
和setName()
方法的接口
public class DBtest{
// arguments are passed using the text field below this editor
public static void main(String[] args){
DataBase database = new DataBase(new Oracle("test"));
DatabaseName databaseName = database.getDataBase();
System.out.println(databaseName.getName());
}
}
interface DatabaseName {
String getName();
}
class DataBase{
private DatabaseName databaseName;
public DataBase(DatabaseName databaseName){
this.databaseName = databaseName;
}
public DatabaseName getDataBase(){
return databaseName;
}
}
class Oracle implements DatabaseName {
private String _databaseName;
public Oracle(String name){
_databaseName = name;
}
public String getName() {
return _databaseName;
}
}
class MongoDB implements DatabaseName {
private String _databaseName;
public MongoDB(String name){
_databaseName = name;
}
public String getName() {
return _databaseName;
}
}
显然DatabaseName
是接口的错误名称,但它是两个类中唯一相同的方法,因此将其称为有意义。关于接口的好处是,只要您知道方法名称,就不必大肆宣传class
使用的内容。
答案 2 :(得分:1)
您必须创建一个接口,然后使用getDatabaseName()方法。然后您的对象Oracle和MongoDB必须实现该接口。 你想要做的是类似于AbstractFactory Pattern。你应该谷歌。
public interface MyDbInterface {
String getDatabaseName();
}
public class HelloWorld {
// arguments are passed using the text field below this editor
public static void main(String[] ){
MyDbInterface dt = DataFactory.create("Oracle");
String name = dt.getDatabaseName();
System.out.println(name);
}
}
public final class DataFactory{
private DataFactory(){
super();
}
public static MyDbInterface create(String type){
MyDbInterface obj = null;
switch(type) {
case("Oracle"):
obj = new Oracle("Test");
break;
case("MongoDB"):
obj = new MongoDB("TestCollection");
break;
}
return obj;
}
}
public class Oracle implement MyDbInterface{
public String databaseName;
public Oracle(String databaseName){
databaseName = databaseName;
}
@Override
public String getDatabaseName() {
return databaseName;
}
}
public class MongoDB implement MyDbInterface{
public String collectionName;
public MongoDB(String collectionName){
collectionName = collectionName;
}
public String getCollectionName() {
return collectionName;
}
@Override
public String getDatabaseName() {
return getCollectionName();
}
}
我来自C#,请查看java风格指南。 ;)
答案 3 :(得分:0)
您应该考虑代码的设计。您需要使用基本的OOP主体来解决问题。有几种方法可以解决您的问题,比如使用interface / generics等。这里我给出了一个这样的例子。
public class HelloWorld {
public static void main(String[] args) {
Data dt = new Data("Oracle");
DataBase obj = dt.GetObject();
String name = obj.getDatabaseName();
System.out.println("Name : "+name);
}
}
class Data {
public String _type;
public Data(String type) {
_type = type;
}
public DataBase GetObject() {
DataBase dataBase=null;
switch (_type) {
case "Oracle":
dataBase = new Oracle();
break;
case "Mongo":
dataBase = new MongoDb();
break;
}
return dataBase;
}
}
interface DataBase {
String getDatabaseName();
}
class Oracle implements DataBase {
public String getDatabaseName() {
return "Oracle";
}
}
class MongoDb implements DataBase {
public String getDatabaseName() {
return "Mongo";
}
}
编辑:
这是解决问题的另一种方法。我相信这种方法可以解决您的问题。
public class HelloWorld {
public static void main(String[] args) {
Data<Oracle> dt = new Data<Oracle>("Oracle");
Oracle obj = dt.getObject();
String name = obj.getDatabaseName();
System.out.println("Name : "+name);
}
}
class Data<T> {
public String _type;
public Data(String type) {
_type = type;
}
public T getObject() {
Object dataBase=null;
switch (_type) {
case "Oracle":
dataBase = new Oracle();
break;
case "Mongo":
dataBase = new MongoDb();
break;
}
return (T)dataBase;
}
}
class Oracle {
public String getDatabaseName() {
return "Oracle";
}
}
class MongoDb {
}