返回

Java "<identifier> expected" 错误详解与解决方案

java

解决 Java 中的 “ expected” 错误

expected” 是 Java 编译器常见的报错信息之一,通常出现在代码语法结构不符合预期的地方,简单来说,就是编译器在特定位置期待的是一个变量名(标识符),但实际得到的却不是。当尝试运行编译Java程序时,就会在控制台输出此类型的错误。这个错误本身是“结果”,而理解错误发生的“原因”才是真正解决问题的关键。本篇文章将针对此问题进行深入分析,并提供相应的解决方法,避免再次遇到同类问题。

错误原因分析

这段报错通常指示代码中存在类型声明或变量赋值的问题。仔细查看报错的代码行,可以发现在类Dfhacktoggle中,出现以下问题:

  • active[] <byte> = 1;
  • inactive[] <byte> = 0;

这些语句尝试对数组activeinactive赋值,同时又使用了<byte>声明,语法有误。Java不允许使用这种方式进行数组赋值。

此外,代码中还有文件相关逻辑的问题:file 类型并不存在。并且没有为fileArray读入数据对应的文件名, Files.readAllBytes(file)file 是一个未声明的变量,将会产生一个 “cannot find symbol” 错误,但这并不妨碍"<identifier> expected"错误产生的原因。同时使用文件名称直接给变量dfhacksdl,vanillasdl,sdl 赋值,这些也是错误的。以及常量 WRITE,也是错误的。
main 方法内的 try 代码块中调用了 vanillasdl.exists(),但是由于其声明的方式错误,以及前面已经存在"<identifier> expected"错误,导致这些逻辑也无法正常执行,在编译时也会出现相关报错,并且无法确定renameTo方法的参数是应该是一个 java.io.File 还是 java.nio.file.Path

简单来说,问题主要在于:变量的声明、赋值以及类型使用了错误的语法。

解决方法

针对上述问题,可以从以下几个方面进行修正:

1. 数组声明和赋值修正

Java中定义数组需要使用标准的类型定义方式,并采用下标访问的方式赋值。修正后的方式应该如下:

   private byte[] active;
   private byte[] inactive;
   
   public Dfhacktoggle(){
       active = new byte[]{1};
       inactive = new byte[]{0};
   }

上述代码,首先正确声明了 activeinactive两个变量的类型为 byte[](字节数组),同时在构造方法中初始化,并且使用数组字面量 {} 初始化值。这种初始化方法简洁高效。

2. 文件相关问题修正

在 Java 中表示文件,需要使用 java.io.File 或者 java.nio.file.Path 类。由于代码中已使用java.nio.file.Path,推荐统一使用 Path。将之前声明的 file 类型,修改为 Path类型,并赋值相应的文本内容。由于原代码直接将dll文件名赋予变量,所以需要使用字符串方式,同时提供一个获取对应 Path 的方法:

    private Path dfhacksdl;
    private Path vanillasdl;
    private Path sdl;
    private Path statusfile;
    
    public Dfhacktoggle(){
       this.dfhacksdl = getPath("SDLdfhack.dll");
       this.vanillasdl = getPath("SDLreal.dll");
       this.sdl = getPath("SDL.dll");
       this.statusfile = getPath("dfhack-status");
    
    active = new byte[]{1};
       inactive = new byte[]{0};
    }
    private Path getPath(String fileName){
         return Path.of(fileName);
     }

同时需要将调用file 的地方进行对应的修改, 例如 Files.readAllBytes(file) 需修改为 Files.readAllBytes(statusfile)
以及将 vanillasdl.exists() 修改为Files.exists(vanillasdl)
sdl.renameTo(dfhacksdl) 等文件重命名操作 修改为 Files.move(sdl,dfhacksdl)

同时需要注意使用 java.nio.file.StandardOpenOption.WRITE 来替代代码中的常量 WRITE
例如Files.write(statusfile, inactive, WRITE); 需改为Files.write(statusfile, inactive, java.nio.file.StandardOpenOption.WRITE);

修改后的完整代码示例

以下是修改后的代码:

package nl.dirkkok.dfhacktoggle;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;

public class Dfhacktoggle {
    private Path dfhacksdl;
    private Path vanillasdl;
    private Path sdl;
    private Path statusfile;

    private boolean dfhack = false;
    private byte[] fileArray = new byte[1];
    private byte[] active;
    private byte[] inactive;
    public Dfhacktoggle() {
        this.dfhacksdl = getPath("SDLdfhack.dll");
        this.vanillasdl = getPath("SDLreal.dll");
        this.sdl = getPath("SDL.dll");
        this.statusfile = getPath("dfhack-status");
        active = new byte[]{1};
        inactive = new byte[]{0};
    }
    private Path getPath(String fileName) {
        return Path.of(fileName);
    }
    
    public static void main(String[] args) {
       Dfhacktoggle dfhacktoggle = new Dfhacktoggle();

       try {
           dfhacktoggle.fileArray = Files.readAllBytes(dfhacktoggle.statusfile);
            if (dfhacktoggle.fileArray[0] == 1) {
                dfhacktoggle.p("DFHack is active. Deactivating...");
                try {
                     if (Files.exists(dfhacktoggle.vanillasdl))
                         throw new IOException("File exists");
                     Files.move(dfhacktoggle.sdl, dfhacktoggle.dfhacksdl);
                    Files.move(dfhacktoggle.vanillasdl,dfhacktoggle.sdl );
                    Files.write(dfhacktoggle.statusfile, dfhacktoggle.inactive, StandardOpenOption.WRITE);
                } catch (IOException x) {
                    dfhacktoggle.errp("DFHack could not be deactivated. Reinstalling the program will solve this.");
                    dfhacktoggle.errp("Detailed info:");
                    dfhacktoggle.errp("IOException: " + x);
                } catch (NoSuchFileException x) {
                   dfhacktoggle.errp("Status file could not be found. Reinstalling the program will solve this.");
                    dfhacktoggle.errp("Detailed info:");
                    dfhacktoggle.errp("NoSuchFileException: " + x);
                }
            } else if (dfhacktoggle.fileArray[0] == 0) {
                dfhacktoggle.p("DFHack is inactive. Activating...");
                try {
                     if (Files.exists(dfhacktoggle.vanillasdl)) throw new IOException("File exists");
                     Files.move(dfhacktoggle.sdl,dfhacktoggle.vanillasdl );
                    Files.move(dfhacktoggle.dfhacksdl,dfhacktoggle.sdl);
                     Files.write(dfhacktoggle.statusfile, dfhacktoggle.active, StandardOpenOption.WRITE);
                } catch (IOException x) {
                    dfhacktoggle.errp("Status could not be checked. Reinstalling the program will solve this.");
                    dfhacktoggle.errp("Detailed info:");
                   dfhacktoggle.errp("IOException: " + x);
                } catch (NoSuchFileException x) {
                   dfhacktoggle.errp("Status file could not be found. Reinstalling the program will solve this.");
                    dfhacktoggle.errp("Detailed info:");
                    dfhacktoggle.errp("NoSuchFileException: " + x);
                }
            } else {
                dfhacktoggle.errp("DFHack's status could not be checked. Reinstalling the program will solve this.");
            }
        } catch (IOException x) {
           dfhacktoggle.errp("Status could not be checked. Reinstalling the program will solve this.");
           dfhacktoggle.errp("Detailed info:");
           dfhacktoggle.errp(x.getMessage());
        }
    }

    public void p(String txt) {
        System.out.println(txt);
    }

    public void errp(String txt) {
        System.err.println(txt);
    }
    
     public void errp(Exception txt) {
        System.err.println(txt.getMessage());
    }
}

代码说明:

修改后的代码可以编译并运行。

  1. 初始化 : activeinactive 两个字节数组通过构造器初始化。
  2. 文件操作 : 使用 java.nio.file.Path 类操作文件路径。使用 java.nio.file.Files 类来进行读取、写入、文件存在检测以及重命名等操作。
  3. 错误处理 : 对可能出现的异常进行捕获和处理。使用try-catch块来捕获文件不存在、IOException 等异常。
  4. 逻辑清晰 : 代码结构更清晰,可读性更强。

安全建议

进行文件操作时,必须注意权限问题。 确保程序有足够的权限来读取和写入目标文件。 在程序运行时,应加入参数校验,避免由于用户传递错误参数导致文件被意外覆盖或删除。

通过上述分析和修改,可以成功解决 Java 程序中 “<identifier> expected” 错误,同时避免其他可能出现的语法错误。在进行开发时,应当仔细阅读编译器的报错信息,这能够帮助快速定位问题,并且能够更好理解代码逻辑。同时熟悉并正确使用java的各种基本数据类型以及操作文件和IO的方法是基础的。