Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么我们可以';不使用构造函数本身初始化servlet吗?_Java_Servlets_Jakarta Ee_Initialization - Fatal编程技术网

Java 为什么我们可以';不使用构造函数本身初始化servlet吗?

Java 为什么我们可以';不使用构造函数本身初始化servlet吗?,java,servlets,jakarta-ee,initialization,Java,Servlets,Jakarta Ee,Initialization,为什么我们必须在servlet中重写init()方法,而我们可以在构造函数中进行初始化,并让web容器在调用构造函数时调用构造函数,将ServletConfig引用传递给servlet 当然,容器必须为此使用反射,但容器无论如何都必须使用反射来调用简单的无参数构造函数,因为构造函数不能是接口的一部分,所以它不能在Servlet API中“正式”指定,这与普通方法不同。此外,由于Java没有析构函数,因此无论如何都需要一个destroy方法,因此它定义了相应的init方法,从而使API更加一致和易

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


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

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


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

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

还有一个历史原因:

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

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

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


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

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

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

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

具体地说,如果要动态加载Java类,应使用以下方法:

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

嗯,无论如何都会使用反射,其附加值是您可以使您的servlet不可变。有许多类的例子,它们在构造函数中进行初始化,但有相应的close方法;几乎每一个流类都是这样工作的。@gustafc,因为无论如何都不应该在servlet中存储(非静态)数据,所以不变性并没有真正的区别。流类就是一个很好的例子;但是请注意,这些是具体的类,而不是接口。在servlet中具有(不可变的)非静态状态有很好的理由。
ServletConfig
的要点是,您可以多次实例化同一个servlet,并让它做(稍微)不同的事情。@Peter,虽然不相关,但我们不是有一个finalize()方法可以用作析构函数吗?@gustafc,很抱歉,我不明白什么是不变性。。。你能解释一下吗?
Object newObject = Class.forName(strFullyQualifiedClassName).newInstance();