Java 当我们关闭一个资源时,对象是否被实例化并销毁?
我的疑问主要是在阅读以下代码中的套接字时产生的:Java 当我们关闭一个资源时,对象是否被实例化并销毁?,java,resources,Java,Resources,我的疑问主要是在阅读以下代码中的套接字时产生的: String hostName = args[0]; int portNumber = Integer.parseInt(args[1]); try ( Socket echoSocket = new Socket(hostName, portNumber); PrintWriter out = new PrintWriter(echoSocket.getOutputSt
String hostName = args[0];
int portNumber = Integer.parseInt(args[1]);
try (
Socket echoSocket = new Socket(hostName, portNumber);
PrintWriter out =
new PrintWriter(echoSocket.getOutputStream(), true);
BufferedReader in =
new BufferedReader(
new InputStreamReader(echoSocket.getInputStream()));
BufferedReader stdIn =
new BufferedReader(
new InputStreamReader(System.in))
) {
String userInput;
while ((userInput = stdIn.readLine()) != null) {
out.println(userInput);
System.out.println("echo: " + in.readLine());
}
链接:
在上面的代码中,据我所知,PrintWriter和BufferedReader是资源,但是我也在trywithreasources块中读取,一旦它结束,其中的所有资源都将关闭。但如果关闭资源意味着销毁对象,则意味着stdIn和in将被销毁,并且它是块外的一个单独实例。是这样吗?看看您对资源的尝试,让我们只考虑零件包装系统
stdIn是一个包装InputStreamReader对象的对象,该对象包装InputStream对象。该InputStream对象是Java进程的标准输入,除非您将其更改为Java进程的标准输入
退出try块时,它将调用stdIn.close,这将在InputStreamReader上级联并调用close,InputStreamReader将级联并调用close,这将在System.in引用的对象上级联并调用close
Java中没有破坏。如果上述变量引用的对象在您的程序中无法访问,它们将被垃圾收集。try with resource语句将只关闭try内部括号中声明的资源
try ( /*anything declared here will be closed*/) {
}
当try结束时,try with资源将对任何声明的资源调用close。这并不一定会像C中的析构函数那样破坏对象,但通常是这样使用的。该变量也将超出try的作用域,因此可以对其进行垃圾收集
在您的示例中,stdIn包装System.IN so System.IN将被关闭。但是,由于在尝试后它仍在作用域中,因此不会对其进行垃圾收集。但是你不能再给它写信了
Try with resource只是syntactic sugar,它将被编译成如下内容:
Socket echoSocket =null
PrintWriter out =null
BufferedReader in =null
BufferedReader stdIn =null
try{
echoSocket = new Socket(hostName, portNumber);
out =
new PrintWriter(echoSocket.getOutputStream(), true);
in =
new BufferedReader(
new InputStreamReader(echoSocket.getInputStream()));
stdIn =
new BufferedReader(
new InputStreamReader(System.in));
String userInput;
while ((userInput = stdIn.readLine()) != null) {
out.println(userInput);
System.out.println("echo: " + in.readLine());
}
}finally{
if(stdIn !=null){
try{
stdIn.close()
}catch(Exception e){
//surpress exception if needed
}
}
if(in !=null){
try{
in.close()
}catch(Exception e){
//surpress exception
}
}
if(out !=null){
try{
out.close()
}catch(Exception e){
//surpress exception
}
}
if(echoSocket !=null){
try{
echoSocket.close()
}catch(Exception e){
//surpress exception
}
}
}
请注意,资源是按相反的顺序关闭的,以解决嵌套问题。如果某个对象在try块中抛出异常,而另一个对象在finally块中抛出异常,那么suppress异常将添加到原始异常对象中,该对象可以通过新的Throwable.getsuppress方法检索。因此stacktrace正确地显示了try中抛出的原始异常
有关“试用资源”的详细信息,请参阅Oracle教程:
如果关闭资源意味着销毁对象
没有。Java中没有“销毁”这样的东西
那就意味着stdIn和in被摧毁了
不,没有
它是块外的一个单独实例。是这样吗
不。是这样的。System.in将被关闭。@SotiriosDelimanolis我认为System.in不会被try with resource关闭,因为它没有在try块的with resource部分声明。@dkatzel stdIn在try with resources中声明。当它的结束被调用时,它将级联到它所包装的读者,依此类推。@SotiriosDelimanolis哦,你的权利。我以为你指的是System.in.@dkatzel是的,我指的是System.in引用的对象。当stdIn关闭时,它就会关闭。好的,这就清楚了。非常感谢。顺便说一句,这个链接已经在我的一个标签页上打开了,我刚通过输入/输出开始联网,只是有点晕过去了。
Socket echoSocket =null
PrintWriter out =null
BufferedReader in =null
BufferedReader stdIn =null
try{
echoSocket = new Socket(hostName, portNumber);
out =
new PrintWriter(echoSocket.getOutputStream(), true);
in =
new BufferedReader(
new InputStreamReader(echoSocket.getInputStream()));
stdIn =
new BufferedReader(
new InputStreamReader(System.in));
String userInput;
while ((userInput = stdIn.readLine()) != null) {
out.println(userInput);
System.out.println("echo: " + in.readLine());
}
}finally{
if(stdIn !=null){
try{
stdIn.close()
}catch(Exception e){
//surpress exception if needed
}
}
if(in !=null){
try{
in.close()
}catch(Exception e){
//surpress exception
}
}
if(out !=null){
try{
out.close()
}catch(Exception e){
//surpress exception
}
}
if(echoSocket !=null){
try{
echoSocket.close()
}catch(Exception e){
//surpress exception
}
}
}