为什么这个局部变量在Java中等于null?

为什么这个局部变量在Java中等于null?,java,variables,local,Java,Variables,Local,我的目标是拥有一个存储文件内容的字符串。我从W3学校()撕下了读取文件的算法,只是做了一些改变 public class Fileparser { public void fileParse(String filename) { try { File myObj = new File("C:\\Users\\(myname)\\Desktop\\" + filename);

我的目标是拥有一个存储文件内容的字符串。我从W3学校()撕下了读取文件的算法,只是做了一些改变

public class Fileparser { 
    
    public void fileParse(String filename) {
        
        
        try {
              File myObj = new File("C:\\Users\\(myname)\\Desktop\\" + filename);
              Scanner myReader = new Scanner(myObj);
              String output = "";
              while (myReader.hasNextLine()) {
                String data = myReader.nextLine();
                output.concat(data);
              }
              myReader.close();
              System.out.println(output);
              
              
            } catch (FileNotFoundException e) {
              System.out.println("An error occurred.");
              e.printStackTrace();
            }
        
        
    
    }

}
当然,大体上,我有一个Fileparser对象,它对我桌面上的一个文件执行该方法,但它完全不打印任何内容。我不得不与Java搏斗,因为我不熟悉局部变量的范围。当我逐行连接到输出时,为什么输出不打印?

必须使用“concat”的返回值

请参阅
.concat
javadocs。它提供了以下内容:

示例: "cares".concat("s") returns "caress" "to".concat("get").concat("her") returns "together" 尽管为了提高效率,我还是建议使用
StringBuilder
,因为您经常连接:

StringBuilder str = new StringBuilder();
while (myReader.hasNextLine()) {
    String data = myReader.nextLine();
    str.append(data);
}
myReader.close();
System.out.println(str.toString());
或者最好是在循环内部而不是外部打印每一行,这将(在大多数情况下)保持文件的原始格式:

Scanner myReader = new Scanner(myObj);
while (myReader.hasNextLine()) {
    String data = myReader.nextLine();
    System.out.println(data);
}
myReader.close();
必须使用“concat”的返回值

请参阅
.concat
javadocs。它提供了以下内容:

示例: "cares".concat("s") returns "caress" "to".concat("get").concat("her") returns "together" 尽管为了提高效率,我还是建议使用
StringBuilder
,因为您经常连接:

StringBuilder str = new StringBuilder();
while (myReader.hasNextLine()) {
    String data = myReader.nextLine();
    str.append(data);
}
myReader.close();
System.out.println(str.toString());
或者最好是在循环内部而不是外部打印每一行,这将(在大多数情况下)保持文件的原始格式:

Scanner myReader = new Scanner(myObj);
while (myReader.hasNextLine()) {
    String data = myReader.nextLine();
    System.out.println(data);
}
myReader.close();

您通常会编写
+=
来附加到字符串,而不是
concat

output += data;
但是,循环中的
+=
concat
(如另一个答案所示,一旦修复)都很慢。更有效的方法是使用:

但实际上这里不需要这样做:直接打印行即可:

while (myReader.hasNextLine()) {
    System.out.println(myReader.nextLine());
}

您通常会编写
+=
来附加到字符串,而不是
concat

output += data;
但是,循环中的
+=
concat
(如另一个答案所示,一旦修复)都很慢。更有效的方法是使用:

但实际上这里不需要这样做:直接打印行即可:

while (myReader.hasNextLine()) {
    System.out.println(myReader.nextLine());
}

因为
output.concat()
不会向
output
指向的字符串添加任何内容:这是不可能的;java中的字符串是不可变的,不能更改

相反,
concat()。像
output=output.concat(data)
这样简单的操作可以完成任务,但请注意,这样的压缩效率非常低。更好:

try {
              File myObj = new File("C:\\Users\\(myname)\\Desktop\\" + filename);
              Scanner myReader = new Scanner(myObj);
              StringBuilder output = new StringBuilder();
              while (myReader.hasNextLine()) {
                String data = myReader.nextLine();
                output.append(data);
              }
              myReader.close();
              System.out.println(output);
              
              
            } catch (FileNotFoundException e) {
              System.out.println("An error occurred.");
              e.printStackTrace();
            }
现在,让我们修复您的错误/枯草人造通行证:

  • 未能安全地关闭资源
  • 未能指定字符集编码,使此代码依赖于操作系统(因此,这是一个bug,并且是一个您无法测试的bug-非常糟糕)
  • 非常愚蠢的异常处理
  • 名为
    parseFile
    的方法显然应该声明为
    抛出IOException
    。这是该方法的固有功能

    然后,对于encore,使用现代API和命名约定:

    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    private static final Path HOME = Paths.get(System.getProperty("user.home"), "Desktop");
    public String parseFile(String fileName) {
        return Files.readString(HOME.resolve(fileName));
    }
    
    看看这有多短,多漂亮。一艘客轮


    注意:“文件”中的方法使用UTF_8作为默认值,而旧的方法使用无用的“平台默认值”。

    因为
    output.concat()
    没有向字符串添加任何内容
    output
    指向:这是不可能的;java中的字符串是不可变的,不能更改

    相反,
    concat()。像
    output=output.concat(data)
    这样简单的操作可以完成任务,但请注意,这样的压缩效率非常低。更好:

    try {
                  File myObj = new File("C:\\Users\\(myname)\\Desktop\\" + filename);
                  Scanner myReader = new Scanner(myObj);
                  StringBuilder output = new StringBuilder();
                  while (myReader.hasNextLine()) {
                    String data = myReader.nextLine();
                    output.append(data);
                  }
                  myReader.close();
                  System.out.println(output);
                  
                  
                } catch (FileNotFoundException e) {
                  System.out.println("An error occurred.");
                  e.printStackTrace();
                }
    
    现在,让我们修复您的错误/枯草人造通行证:

  • 未能安全地关闭资源
  • 未能指定字符集编码,使此代码依赖于操作系统(因此,这是一个bug,并且是一个您无法测试的bug-非常糟糕)
  • 非常愚蠢的异常处理
  • 名为
    parseFile
    的方法显然应该声明为
    抛出IOException
    。这是该方法的固有功能

    然后,对于encore,使用现代API和命名约定:

    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    private static final Path HOME = Paths.get(System.getProperty("user.home"), "Desktop");
    public String parseFile(String fileName) {
        return Files.readString(HOME.resolve(fileName));
    }
    
    看看这有多短,多漂亮。一艘客轮


    注意:“文件”中的方法使用UTF_8作为默认值,而旧的方法使用无用的“平台默认值”。

    如下图所示更改程序,使其按需工作。 这里,字符串的行为是当您创建一个新对象时,它总是将这些对象保留在字符串池中,并返回一个新的对象,因此您需要指定给现有的字符串对象以连接所有字符串对象

    当具有多个连接时,始终建议使用StringBuilder

    public class Fileparser { 
        
        public void fileParse(String filename) {
        
        
        try {
              File myObj = new File("C:\\Users\\(myname)\\Desktop\\" + filename);
              Scanner myReader = new Scanner(myObj);
              String output = "";
              while (myReader.hasNextLine()) {
                String data = myReader.nextLine();
               output= output.concat(data);
              }
              myReader.close();
              System.out.println(output);
              
              
            } catch (FileNotFoundException e) {
              System.out.println("An error occurred.");
              e.printStackTrace();
            }
    }
    

    }

    如下图所示更改程序,使其按照您的需要工作。 这里,字符串的行为是当您创建一个新对象时,它总是将这些对象保留在字符串池中,并返回一个新的对象,因此您需要指定给现有的字符串对象以连接所有字符串对象

    当具有多个连接时,始终建议使用StringBuilder

    public class Fileparser { 
        
        public void fileParse(String filename) {
        
        
        try {
              File myObj = new File("C:\\Users\\(myname)\\Desktop\\" + filename);
              Scanner myReader = new Scanner(myObj);
              String output = "";
              while (myReader.hasNextLine()) {
                String data = myReader.nextLine();
               output= output.concat(data);
              }
              myReader.close();
              System.out.println(output);
              
              
            } catch (FileNotFoundException e) {
              System.out.println("An error occurred.");
              e.printStackTrace();
            }
    }
    
    }

    声明:“
    String
    s是常量;它们的值在创建后不能更改。”因此,返回一个新的
    String
    ,表示连接。将此行替换为
    output=output.concat(数据)。声明:“
    String
    s是常量;它们的值在创建后不能更改。”因此,返回一个新的
    String
    ,表示连接。将此行替换为
    output=output.concat(数据)