java 为什么我们不能使用构造函数本身来初始化 servlet?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2920616/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 23:28:07  来源:igfitidea点击:

why we can't initialize a servlet using constructor itself?

javaservletsjakarta-eeinitialization

提问by Reddy

Why do we have to override init() method in Servlets while we can do the initialization in the constructor and have web container call the constructor passing ServletConfig reference to servlet while calling constructor?

为什么我们必须覆盖 Servlets 中的 init() 方法,而我们可以在构造函数中进行初始化,并让 web 容器调用构造函数并在调用构造函数时将 ServletConfig 引用传递给 servlet?

Ofcourse container has to use reflection for this but container has to use reflection anyway to call a simple no-arg constructor

当然容器必须为此使用反射,但容器无论如何都必须使用反射来调用简单的无参数构造函数

回答by Péter T?r?k

Since a constructor can not be part of an interface, it can not be "formally" specified within the Servlet API, unlike normal methods. Moreover, since Java has no destructors, a destroymethod is needed anyway, so it defining the corresponding initmethod makes the API more consistent and easier to use.

由于构造函数不能是接口的一部分,因此与普通方法不同,它不能在 Servlet API 中“正式”指定。而且,由于Java没有析构函数,destroy所以无论如何都需要一个方法,所以定义相应的init方法使API更加一致,更易于使用。

Using reflection to detect/verify constructor parameters would just unnecessarily complicate things, and I don't see any added value.

使用反射来检测/验证构造函数参数只会不必要地使事情复杂化,而且我看不到任何附加值。

回答by leopoldkot

Servlet object has a well-defined life cycle where creation and initialization steps are distinct. Usually you don't want to do heavy and unreliable work in constructors, e.g. getting DB connection pool or initializing cache. You have a chance to do it after a Servlet object is successfully created.

Servlet 对象具有明确定义的生命周期,其中创建和初始化步骤是不同的。通常你不想在构造函数中做繁重和不可靠的工作,例如获取数据库连接池或初始化缓存。成功创建 Servlet 对象后,您就有机会执行此操作。

Also, here http://oreilly.com/catalog/jservlet/chapter/ch03.htmlis a historical reason:

另外,这里http://oreilly.com/catalog/jservlet/chapter/ch03.html是一个历史原因:

The init() method is typically used to perform servlet initialization--creating or loading objects that are used by the servlet in the handling of its requests. Why not use a constructor instead?Well, in JDK 1.0 (for which servlets were originally written), constructors for dynamically loaded Java classes (such as servlets) couldn't accept arguments.

So, in order to provide a new servlet any information about itself and its environment, a server had to call a servlet's init() method and pass along an object that implements the ServletConfig interface.

Also, Java doesn't allow interfaces to declare constructors. This means that the javax.servlet.Servlet interface cannot declare a constructor that accepts a ServletConfig parameter. It has to declare another method, like init(). It's still possible, of course, for you to define constructors for your servlets, but in the constructor you don't have access to the ServletConfig object or the ability to throw a ServletException.

init() 方法通常用于执行 servlet 初始化——创建或加载 servlet 在处理其请求时使用的对象。为什么不使用构造函数呢?嗯,在 JDK 1.0(最初为它编写 servlet)中,动态加载的 Java 类(例如 servlet)的构造函数不能接受参数。

因此,为了向新的 servlet 提供有关其自身及其环境的任何信息,服务器必须调用 servlet 的 init() 方法并传递一个实现 ServletConfig 接口的对象。

此外,Java 不允许接口声明构造函数。这意味着 javax.servlet.Servlet 接口不能声明接受 ServletConfig 参数的构造函数。它必须声明另一个方法,例如 init()。当然,您仍然可以为您的 servlet 定义构造函数,但在构造函数中,您无权访问 ServletConfig 对象或抛出 ServletException 的能力。

回答by Michael

One reason is that you don't have access to the ServletConfig object in the constructor. The ServletConfig object is created afterthe constructor is called and beforeinit() is called. So, you cannot access servlet init parameters in the constructor.

原因之一是您无权访问构造函数中的 ServletConfig 对象。ServletConfig 对象是在调用构造函数之后和调用init()之前创建的。因此,您无法在构造函数中访问 servlet init 参数。

回答by Balamurugan

Servlet implementation classes can have constructor but they should be using init() method to initialize Servlet because of two reasons, first you cannot declare constructors on interface in Java, which means you cannot enforce this requirement to any class which implements Servlet interface and second, Servlet require ServletConfig object for initialization which is created by container as it also has reference of ServletContext object, which is also created by container.

Servlet 实现类可以有构造函数,但它们应该使用 init() 方法来初始化 Servlet,原因有两个,首先你不能在 Java 接口上声明构造函数,这意味着你不能将此要求强制执行到任何实现 Servlet 接口的类,其次, Servlet 需要 ServletConfig 对象进行初始化,该对象由容器创建,因为它也有 ServletContext 对象的引用,该对象也是由容器创建的。

Servlet is an interface defined in javax.servlet package and HttpServlet is a class and like any other class in Java they can have constructor, but you cannot declare constructor inside interface in Java. If you don't provide an explicit constructor than compiler will add a default no argument constructor in any Servlet implementation class. Another reason that you should not initialize Servlet using constructor because Servlets are not directly instantiated by Java code, instead container create there instance and keep them in pool. Since containers from web servers like Tomcat and Jetty uses Java Reflection for creating instance of Servlet, presence of no argument constructor is must. So, by any chance if you provide a parametric constructor and forget to write a no argument constructor, web container will not be able to create instance of your Servlet, since there is no default constructor. Remember Java compiler doesn't add default no argument constructor, if there is a parametric constructor present in class. That's why it's not advised to provide constructor in Servlet class.

Servlet 是在 javax.servlet 包中定义的接口,而 HttpServlet 是一个类,就像 Java 中的任何其他类一样,它们可以有构造函数,但不能在 Java 的接口内部声明构造函数。如果您不提供显式构造函数,那么编译器将在任何 Servlet 实现类中添加一个默认的无参数构造函数。另一个不应该使用构造函数初始化 Servlet 的原因是因为 Servlet 不是由 Java 代码直接实例化的,而是容器在那里创建实例并将它们保存在池中。由于来自 Tomcat 和 Jetty 等 Web 服务器的容器使用 Java 反射来创建 Servlet 实例,因此必须存在无参数构造函数。因此,万一您提供了一个参数构造函数而忘记编写一个无参数构造函数,web 容器将无法创建 Servlet 的实例,因为没有默认构造函数。请记住,如果类中存在参数构造函数,则 Java 编译器不会添加默认的无参数构造函数。这就是为什么不建议在 Servlet 类中提供构造函数的原因。

回答by fisherman

In JDK 1.0 (for which servlets were originally written), constructors for dynamically loaded Java classes (such as servlets) couldn't accept arguments. So, in order to provide a new servlet any information about itself and its environment, a server had to call a servlet's init() method and pass along an object that implements the ServletConfig interface. see:doc

在 JDK 1.0(最初为其编写 servlet)中,动态加载的 Java 类(例如 servlet)的构造函数不能接受参数。因此,为了向新的 servlet 提供有关其自身及其环境的任何信息,服务器必须调用 servlet 的 init() 方法并传递一个实现 ServletConfig 接口的对象。见:文档

In detail,If you want to dynamically load a Java class, you should use the following method:

详细来说,如果你想动态加载一个Java类,你应该使用下面的方法:

Class<MyClass> clazz = MyClass.class;
Constructor<MyClass> ctor = clazz.getDeclaredConstructor(String.class);
MyClass instance = ctor.newInstance("foo");

But, the method which returns a Constructor object in the Class class has been written since jdk1.1. In jdk1.0, you can only use the following parameterless method:

但是,在Class类中返回一个Constructor对象的方法是从jdk1.1开始写的。在jdk1.0中,只能使用以下无参方式:

Object newObject = Class.forName(strFullyQualifiedClassName).newInstance();