【问题标题】:Instantiate Java Abstract class? [duplicate]实例化Java抽象类? [复制]
【发布时间】:2015-07-11 08:54:05
【问题描述】:

相对较新的 Java 程序员和我被告知不能创建抽象类的实例。我也做了一些研究,我了解到,在大多数情况下,当它出现一个抽象类正在创建时,它实际上是一个匿名子类。但这是我遇到的问题:

Java 的URL 类有一个方法openConnection,它返回一个URLConnectionURLConnection 是一个抽象类,Java 文档也将它的所有子类列为抽象类......所以我真的迷路了。返回什么?

【问题讨论】:

  • URLConnection 的子类,就像你说的那样。
  • 返回的URLConnection的具体类可能标记为private
  • 这里将应用多态概念。类的类型将是 URLConnction,您将返回其子类的实例
  • 仅针对这种情况:System.out.println(theConnection.getClass()); 将为您提供答案(当然,没有任何解释为什么它正是 this...)

标签: java instantiation abstract urlconnection


【解决方案1】:

返回的是您在 API 文档中找不到的非抽象子类,例如 sun.net.www.protocol.http.HttpUrlConnection。如果您从浏览器中的小程序运行相同的代码,您可能会得到不同的代码,通常是封装了浏览器本机连接的代码。

所以没有什么技巧,也没有什么魔法,只是有些类没有出现在 API 文档中,因为它们被认为是实现内部的并且可能会发生变化。

有很多类似的例子,DocumentBuilderFactoryTransformerFactory 都是抽象的,但它们的 newInstance() 方法会返回一个子类,通常是单独打包的(例如Saxon)。

但同样的问题也有不同的解决方案:JDBC 定义了Driver 接口(而不是抽象类),以及一个带有静态方法的DriverManager 实用程序类来加载不同的驱动程序实现。数据库驱动程序供应商需要实现Driver 接口,而不是扩展抽象类。

顺便说一句,要找到对象的实际运行时类,只需在它们上调用getClass()即可。

【讨论】:

  • This answer from another question 进一步解释了为什么这些类不在文档中。
【解决方案2】:

openConnection 返回一些扩展URLConnection 的具体类。该方法的签名被定义为返回URLConnection,因为您使用它的代码不应依赖于任何特定的实现。

【讨论】:

  • 这个答案中的一切都是正确的,但我认为它不能回答关于实际返回什么的问题。
【解决方案3】:

多态概念将适用于此。

对象的类型将是 URLConnection(父类\接口),对象将是其子类(扩展或实现(在接口的情况下))。

以下示例可能会让您清楚这一点。

abstract class URLConnection {
  // some methods. 
}

假设您有自己的班级。

class ConnectionClass extends URLConnection {
  // some methods 
} 

class Main {
  URLConnection connect = null

  public URLConnection getUrl() {
    return connect = new ConnectionClass();
  }
}

您将返回类的对象,该对象提供了openConnection()URLConnection 类的实现。相同的概念适用于接口案例。

【讨论】:

    【解决方案4】:

    可能是Anonymous Class

    假设你有一个abstract class...

    abstract class Vehicle {
        abstract public void move();
    }
    

    无需创建class Car extends Vehicleclass Boat extends Vehicle,您就可以借助匿名类的魔力做到这一点。 (这可能是 javadoc 没有说有子类的原因,因为它是匿名的,因此不能被 javadoc 所代表的公共 api 引用。)

    class Example {
    
        public Vehicle foo() {
    
            Vehicle car = new Vehicle {
                @Override
                public void move() {
                    // do some car movement, i.e. driving
                }
            }
    
            return car;
        }
    
        public Vehicle bar() {
    
            Vehicle boat = new Vehicle {
                @Override
                public void move() {
                    // do some boat movement, i.e. boating
                }
            }
    
            return boat;
        }
    }
    

    所以你不能实例化abstract class...但这并不是全部事实,你可以将它作为一个匿名类并在现场实现方法。虽然从技术上讲,这并不是实例化 abstract class,但当你看到这种事情时,它会做很多事情。


    可以是私人的Inner Class

    再说一遍,假设你有一个abstract class...

    abstract class Vehicle {
        abstract public void move();
    }
    

    如果内部classprivate,那么只有封装它的类才能实例化它。 (这可能是 javadoc 没有说有子类的原因,因为它是私有的,因此对 javadoc 所代表的公共 api 隐藏。)

    class Example {
    
        private class Car extends Vehicle {
            @Override
            public void move() {
                // do some car movement, i.e. driving
            }
        }
    
        private class Boat extends Vehicle {
            @Override
            public void move() {
                // do some boat movement, i.e. boating
            }
        }
    
        public Vehicle foo() {
            return new Car();
        }
    
        public Vehicle bar() {
            return new Boat();
        }
    }
    

    这并不能解释关于实例化abstract classes 的任何内容,但它可能有助于回答有关URLopenConnectionURLConnection 的问题。

    【讨论】:

      【解决方案5】:

      这是一个扩展 URLConnection 的类,正在返回。这是一种隐藏实现细节的方法,因为可以根据输入参数返回不同的URLConnection 实现。

      【讨论】:

        【解决方案6】:

        如果所有子类都是抽象的,那是因为你只能通过在工厂中创建类来使用这些类。如果您仔细检查 Using java.net.URLConnection to fire and handle HTTP requests 中的代码,您将看到 URLConnection 对象从未实例化。相反,我们通过像这样调用openConnection 来获取它:

        URLConnection connection = new URL(url + "?" + query).openConnection();
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-09-08
          • 1970-01-01
          • 2017-02-05
          • 1970-01-01
          相关资源
          最近更新 更多