在java中将对象传递给另一个类引用有什么用?

What is the use of passing object to another class reference in java?

例如:foo();AB =新的狗

节能型到另一个类的对象引用另一个类的大学!


是的,如果foo是一个接口,那么这种方法可以让您对代码有更多的控制。实现了EDCOX1、2、EDCOX1、3、EDCOX1、4和EDCOX1、5、Java编程语言的特点。

假设您要从应用程序连接到Oracle并编写这样的代码

1
2
    OracleDrive driver= new OracleDriver()
    driver.connect();

它会解决你的问题。但会使您的代码与OracleDriver紧密耦合。如果从类路径中删除与Oracle相关的JAR,则应用程序根本不会编译。如果有人要求您根据配置将应用程序连接到不同的DBS,那么您最终会得到基于您的应用程序支持的DBS的多个if。按照编程标准,这是不好的做法。

如果您所有的DB驱动器都实现了一个接口Driver,那么您可以根据配置加载驱动程序,而无需将您的代码紧密耦合到任何特定的驱动程序类,如

1
2
Driver driver = properties.get(db.driver.class)
driver.connect()

现在您看到需要更改应用程序以连接到MySQL,只需要在配置文件中设置该类。

希望你明白我的意思!


并不总是需要做像Foo foo = new Bar()这样的事情,但通常建议引用接口而不是实现。这样,您就可以在不需要更改其他代码的情况下更改实现。例如,如果您正在处理列表,并且使用ArrayList,则可能会执行以下操作:

1
2
ArrayList<Integer> numbers = new ArrayList<>();
//Do stuff with numbers

不过,你可能不在乎它是什么样的列表,所以你可能会更好地

1
2
List<Integer> numbers = new ArrayList<>();
//Do stuff with numbers

现在,不管你有什么样的列表,也许你会发现LinkedList的性能会更好,你可以使用它而不是更改任何其他代码。

不过,当其他调用方接收对象时,多态性是最重要的。


它对方法参数更有用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Animal {
    public boolean hasHair = true;
    public void speak() {}
}

class Dog extends Animal {
    public void speak() {
        System.out.println("Woof!");
    }
}

class Person {
    public void shave(Animal a) {
        a.hasHair = false;
        a.speak();
    }
}

class Main {
    public static void main(String[] args) {
        Person joe = new Person();
        Dog fido = new Dog();
        joe.shave(fido);
    }
}

在这种情况下,一个人可以剃任何动物的毛,但我们把它当作狗。

因为我们知道菲多是一只狗,所以Animal fido = new Dog();就没那么有用了,但是考虑一下:

1
2
3
4
5
Animal pet;
if(joe.prefersCats)
    pet = new Cat();
else
    pet = new Dog();


您总是可以用对子类的引用代替基类。

换句话说,你可以用一些更具体的东西来代替更一般的东西,所以如果你有一行代码要求一只狗,你可以把它作为参考发送给一只狗。所以这行代码:

1
Foo ab=new Dog();

意味着您正在实例化一个新的Dog对象,然后创建一个Foo引用称为ab并指向该对象。


请看我的一个老答案:

使用接口有什么好处

这是我的一位教授曾经告诉我们的一件轶事。

长话短说,当你进入更复杂的系统时,你想要这样做的原因就变得更清楚了。将规范(接口/抽象类及其契约)与实现(具体类)分离的能力是一个强大的工具,它使编写新的实现变得非常容易,而不必在应用程序的其他地方更改代码。您在代码中使用规范,例如规范:

1
public interface Animal { ... }

您的实施:

1
public class Dog implements Animal { ... }

然后在代码中,尽可能使用规范:

1
2
Animal a = new Dog();
a.eat(); // All animals eat, so eat() is on the Animal interface

除非您绝对需要使用实现本身:

1
2
Dog d = new Dog();
d.bark(); // Other animals don't bark, so we need to have the Dog here

这会使代码更清晰。例如,假设我有一个方法feedAndGroom。如果我没有接口,我需要为我想要支持的每种动物创建一个新的方法:

1
2
3
4
5
public static void feedAndGroom(Cat c) { ... }

public static void feedAndGroom(Dog d) { ... }

public static void feedAndGroom(Turtle t) { ... }

根据具体情况,每个代码块甚至可能看起来完全相同。更糟糕的是,当有人发现一只新动物时会发生什么?我们每次都必须添加一个新方法,这将导致大量的方法。所有这些重复的解决方案是围绕功能创建一个接口,然后使用一种方法:

1
public static void feedAndGroom(Animal a) { ... }

这需要实现Animal接口的任何东西。所有这些方法调用都是合法的:

1
2
3
feedAndGroom(new Cat());
feedAndGroom(new Dog());
feedAndGroom(new Turtle());

但是,这些方法调用也是合法的:

1
2
3
feedAndGroom(new Hyena());
feedAndGroom(new Lion());
feedAndGroom(new Panther());

我们可能不想尝试喂养和培育这些动物,至少不想饲养野生动物,因此我们可以添加一个名为DomesticatedAnimal的新接口,扩展Animal

1
public interface `DomesticatedAnimal` extends `Animal` { ... }

将我们的方法改为:

1
public static void feedAndGroom(DomesticatedAnimal da) { ... }

然后,DogCatTurtle类将实现DomesticatedAnimal,而不是执行Animal。例如:

1
public class Dog implements DomesticatedAnimal { ... }

这意味着,由于Dog直接实现了DomesticatedAnimal,因此Dog既是DomesticatedAnimal,又是Animal,因为DomesticatedAnimal扩展了Animal。其他动物,HyenaLionPanther只是实现Animal接口。这意味着我们的新方法不会像我们原来的方法那样只采用任何Animal,而是将其限制在特定类型的Animal对象上。同时,任何使用原始Animal接口的方法仍然适用于所有相关对象。


这种类型的声明只可能

1
 Foo ab=new Dog();

如果dog类扩展了类foo,或者foo是一个接口,由dog类实现为

1
class Dog extends Foo { .... }

1
class Dog implements Foo { ... } //Here Foo is an interface

我认为如果用继承的接口或继承的类初始化类对象作为所有的基类函数,那么属性将在派生类对象中可用。如果用不同的派生类初始化具有相同基类的多个对象,这种类型的声明将非常有用。例如,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class MyObject
{
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

public class MyFile extends MyObject
{
    private String extension;

    public String getExtension() {
        return extension;
    }

    public void setExtension(String extension) {
        this.extension = extension;
    }
}

public class MyFolder extends MyObject
{

}

如果正在初始化

1
MyObject file = new MyFile();

这确实没有用,但当我们想要初始化

1
2
3
List<MyObject> listOfFilesFolders = new ArrayList<MyObject>();
listOfFilesFolders.add(new MyFile());
listOfFilesFolders.add(new MyFolder());

此"listofilesfolders"可以是另一个类的私有变量,该类保持存在文件/文件夹列表。

或者我们想有一个功能

1
2
3
4
private void SomeFunction(MyObject obj)
{

}

它可以获取从基类派生的所有对象,并根据基类属性或函数执行操作。


简单的答案,你不能这样做。

更复杂的答案是,只有当"狗"是"foo"的类型时,你才能做到这一点。什么时候我们会说dog是"foo"的类型,如果dog实现foo(如果是接口)或扩展foo(如果是其他类或抽象类)

现在,到接口编码(问题的技术名称)的好处是

1)Java的多态性是基于此的(多态性使得行为的运行时改变成为可能,请在Java中使用谷歌多态性获得更多信息)2)您通过这种方法使接口独立于实现。

希望这能回答你的问题。