【问题标题】:Changing values of static class variables in a nested loop在嵌套循环中更改静态类变量的值
【发布时间】:2013-12-26 03:51:34
【问题描述】:

我在更改嵌套循环中的类变量的值时遇到问题 - 我不知道为什么。我猜这是因为变量是static。但它是一个静态方法,因为它用于从文件中列出系统中的用户,所以它必须是静态的(我从 main 方法调用它以将文件读取到 TreeMaps)。不能从方法中重写静态类变量吗?如果可能的话——我到底做错了什么?

public class Loan{

protected int noOfLoans;
protected int noOfReturns;
protected User user=new User();
protected static Book book= new Book();
protected Map <Integer, Book> currentLoans=new TreeMap <Integer, Book>();
protected Map <Integer, Book> returned=new TreeMap <Integer, Book>();   
protected static Map<Integer, Loan> loanList=new TreeMap<Integer, Loan>();

public static void main(String[] args){
    readLoans();
}

public static void readLoans(){
    loanList.clear();
    BufferedReader reader = null;
    try {
        reader=new BufferedReader(new FileReader("loans.txt"));
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    String line = null;
    try {
        line = reader.readLine();
    } catch (IOException e) {
        e.printStackTrace();
    }
    while (line!=null) {
        String[] splitOut=line.split("-");
        String[] loan_User=splitOut[0].split(",");
        String[] loan_CurrentLoans=splitOut[2].split(",");
        String[] loan_Returned=splitOut[4].split(",");
        Loan loan = new Loan();
        loan.user.setFirstName(loan_User[0]);
        loan.user.setSurname(loan_User[1]);
        loan.user.setPersonalID(loan_User[2]);
        for (int i = 1; i <= Integer.parseInt(splitOut[1]); i++) {
            book.setName(loan_CurrentLoans[((Integer.parseInt
                    (splitOut[1])-1)*4)]);
            book.setAuthorFirstname(loan_CurrentLoans[((Integer.parseInt
                    (splitOut[1])-1)*4)+1]);
            book.setAuthorSurname(loan_CurrentLoans[((Integer.parseInt
                    (splitOut[1])-1)*4)+2]);
            book.setISBN(loan_CurrentLoans[((Integer.parseInt
                    (splitOut[1])-1)*4)+3]);
            loan.currentLoans.put(i, book);
        }
        for (int i = 1; i <= Integer.parseInt(splitOut[3]); i++) {
            book.setName(loan_Returned[((Integer.parseInt
                    (splitOut[3])-1)*4)]);
            book.setAuthorFirstname(loan_Returned[((Integer.parseInt
                    (splitOut[3])-1)*4)+1]);
            book.setAuthorSurname(loan_Returned[((Integer.parseInt
                    (splitOut[3])-1)*4)+2]);
            book.setISBN(loan_Returned[((Integer.parseInt
                    (splitOut[3])-1)*4)+3]);
            loan.returned.put(i, book);
        }
        loan.setNoOfLoans(Integer.parseInt(splitOut[1]));
        loan.setNoOfReturns(Integer.parseInt(splitOut[3]));
        loanList.put(loanList.size()+1, loan);
        try {
            line=reader.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    try {
        reader.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
}

这是一个输入行供参考:

John,Doe,8012311213-2-a book,Author,Authorson,1234567890123,another book,Author,Authorson,2345678901234-1-a returned book,Author,Authorson,3456789012345

在上面打印时我希望得到什么:

Current Loans:
1. a book by Author Authorson (1234567890123)
2. another book by Author Authorson (2345678901234)

Returned Loans:
1. a returned book by Author Authorson (3456789012345)

我目前得到的:

Current Loans:
1. a book by Author Authorson (1234567890123)
2. a book by Author Authorson (1234567890123)

Returned Loans:
1. a book by Author Authorson (1234567890123)

readLoans();
System.out.println(loanList.get(2).currentLoans.get(1).toString());
System.out.println(loanList.get(2).currentLoans.get(2).toString());

返回

a returned book by Author Authorson (3456789012345)
a returned book by Author Authorson (3456789012345)

这让我相信我实际上无法创建静态 Book 对象的实例,但必须使其成为非静态对象并尝试在方法中创建对象的实例。如果是这样 - 我该怎么做?

【问题讨论】:

  • 您是否尝试过调试您的代码并实际看到一步一步发生的事情?
  • 当然,您不能创建静态对象的实例,这就是静态对象和非静态对象之间的全部区别。静态对象属于类本身。

标签: java loops object static instance


【解决方案1】:

从这里开始,很难理解你怎么能像你一样理解,但同时又如此困惑。我并不是要侮辱 - 只是说我完全不确定我了解你在哪里。

使用new 创建实例。所以在你的两个循环中,你一直覆盖一本静态书,而不是你需要一个局部变量,你分配一个 new 书,然后设置字段。

【讨论】:

    【解决方案2】:

    问题不在于您的 Book 是静态的,更简单的问题在于每次在循环期间更改它时它都是同一个对象。确实会发生这种情况,因为您已将其声明为静态字段,但您以错误的方式思考它。

    让我们简化问题,而不是一本书,用它来说明:

    class AnObject {
        int aValue;
    }
    

    而不是 IO,只需循环几次并将其添加到列表中:

    class PersistenceOfChangesDemo {
        static List<AnObject> theList = new ArrayList<AnObject>();
    
        public static void main(String[] args) {
            AnObject theObject = new AnObject();
    
            for(int i = 1; i <= 3; i++) {
                /* reassign the object's value */
                theObject.aValue = i;
                /* adds the same object each time */
                theList.add(theObject);
            }
    
            /* theList is now of size 3
             * but all its elements refer to the same object (theObject) */
            for(AnObject anObject : theList) {
                /* prints '3' every time
                 * because that was the last value assigned */
                System.out.println(anObject.aValue);
                /* prints 'true' every time */
                System.out.println(anObject == theObject);
            }
        }
    }
    

    解决方案是每次想要一个新对象时都需要创建一个新对象:

    class PersistenceOfChangesDemo {
        static List<AnObject> theList = new ArrayList<AnObject>();
    
        public static void main(String[] args) {
    
            for(int i = 1; i <= 3; i++) {
                /* make a new object each time */
                AnObject anObject = new AnObject();
    
                anObject.aValue = i;
                theList.add(anObject);
            }
    
            /* theList now has references to 3 different objects */
            for(AnObject anObject : theList) {
                /* prints 1, 2, 3 */
                System.out.println(anObject.aValue);
            }
        }
    }
    

    根据您的评论,确保每次将其放入地图时都在创建新实例:

    for (int i = 1; i <= Integer.parseInt(splitOut[1]); i++) {
        Book newBook = new Book();
    
        newBook.setName(loan_CurrentLoans[((Integer.parseInt
                (splitOut[1])-1)*4)]);
        newBook.setAuthorFirstname(loan_CurrentLoans[((Integer.parseInt
                (splitOut[1])-1)*4)+1]);
        newBook.setAuthorSurname(loan_CurrentLoans[((Integer.parseInt
                (splitOut[1])-1)*4)+2]);
        newBook.setISBN(loan_CurrentLoans[((Integer.parseInt
                (splitOut[1])-1)*4)+3]);
        loan.currentLoans.put(i, newBook);
    }
    

    【讨论】:

    • 即使在每个 for 循环中创建 Book 对象的新实例,我仍然得到相同的结果。我相信这是因为我的两个 for 循环嵌套在一个 while 循环中,因此我一直在编辑对象 Book 的同一个实例,因为它是在 while 循环中实例化的。因此,每隔一段时间就会创建一个新实例。我说的对吗?
    • @JerriKangasniemi 如果你不在 for 循环中调用 new Book,那么你就不会创建一个新的。如果您的新代码看起来像我的编辑并且您正在为每个put 创建一个新对象,那么您可能会遇到另一个问题。在这种情况下,我建议在 while 循环之前插入一个断点进行调试。例如,您的字符串拆分索引可能是错误的,您需要查看实际存储到每本书的内容。
    【解决方案3】:

    这只是参考问题。这三个都指向同一个对象static book,所以代表最后插入的相同细节。

    更改只是创建Book() 的新对象,而不是使用相同的对象来处理不同的细节。

    试试下面的代码

    Loan loan = new Loan();
            loan.user.setFirstName(loan_User[0]);
            loan.user.setSurname(loan_User[1]);
            loan.user.setPersonalID(loan_User[2]);
            for (int i = 1; i <= Integer.parseInt(splitOut[1]); i++) {
                book = new Book();          // added this line
                book.setName(loan_CurrentLoans[((Integer.parseInt
                        (splitOut[1])-1)*4)]);
                book.setAuthorFirstname(loan_CurrentLoans[((Integer.parseInt
                        (splitOut[1])-1)*4)+1]);
                book.setAuthorSurname(loan_CurrentLoans[((Integer.parseInt
                        (splitOut[1])-1)*4)+2]);
                book.setISBN(loan_CurrentLoans[((Integer.parseInt
                        (splitOut[1])-1)*4)+3]);
                loan.currentLoans.put(i, book);
            }
            for (int i = 1; i <= Integer.parseInt(splitOut[3]); i++) {
                    book = new Book();           // added this line
                book.setName(loan_Returned[((Integer.parseInt
                        (splitOut[3])-1)*4)]);
                book.setAuthorFirstname(loan_Returned[((Integer.parseInt
                        (splitOut[3])-1)*4)+1]);
    

    【讨论】:

    • 即使在创建 Book 对象的新实例时,我仍然得到相同的结果。我相信这是因为我的两个 for 循环嵌套在一个 while 循环中,因此我一直在编辑对象 Book 的同一个实例,因为它是在 while 循环中实例化的。因此,每隔一段时间就会创建一个新实例。我说的对吗?
    • 现在检查上面的编辑。回复此更改是否有效?
    【解决方案4】:

    我是怎么解决的;

    public static void readLoans(){
        // Reads the bookList and userList.
        readBooks();
        readUsers();
        // Creates a new BufferedReader and tries to read "loans.txt"
        BufferedReader reader = null;
        try {
            reader=new BufferedReader(new FileReader("loans.txt"));
        }
        // Catches exception if "books.txt" does not exist.
        catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        String line = null;
        // tries to read the first line and interpret it as a String.
        try {
            line = reader.readLine();
        } 
        // Catches IOexception if any is thrown when trying to read line.
        catch (IOException e) {
            e.printStackTrace();
        }
        // Loop as long as "line" is not empty, i.e. as long as a Loan is read.
        while (line!=null) {
            // split the String "line" at every RegEx "-"
            String[] splitOut=line.split("-");
            // Create a String from the first index of the first split.
            String user = splitOut[0];
            /* Split the second and third index of the first split and create
             * new Stringarrays from them.*/
            String[] loans = splitOut[1].split(",");
            String[] returns = splitOut[2].split(",");
            User aUser = new User();
            /* Find the user in the userList whose personal ID matches the 
             * String "user" that we created. This is the user that we want to
             * create (a) loan/s and/or (a) returned loan/s for.*/
            for (int i = 1; i < userList.size()+1; i++) {
                if (userList.get(i).getPersonalID().equals(user)) {
                    /*Set the variables for the User.*/
                    aUser.setFirstname(userList.get(i).getFirstname());
                    aUser.setSurname(userList.get(i).getSurname());
                    aUser.setPersonalID(userList.get(i).getPersonalID());
                    aUser.setTelephone(userList.get(i).getTelephone());
                    aUser.setLoans(userList.get(i).getLoans());
                    aUser.setReturns(userList.get(i).getReturns());
                    // Create an ArrayList for Loans and Returns for every user
                    ArrayList<Loan> listOfloans = new ArrayList<Loan>();
                    ArrayList<Loan> listOfreturns = new ArrayList<Loan>();
                    // if the new user has any loans...
                    for (int j = 0; j < aUser.getLoans(); j++) {
                        for (int k = 1; k < bookList.size()+1; k++) {
                            /* ... find the "Book" object with the
                             * corresponding ISBN...*/
                            if (bookList.get(k).getIsbn().equals(loans[j*3])) {
                                // ...then create a new loan object for each...
                                Loan loan = new Loan();
                                // ...and set the variables of each loan...
                                loan.setTitle(bookList.get(k).getTitle());
                                loan.setAuthor_firstname(bookList.get(k).
                                        getAuthor_firstname());
                                loan.setAuthor_surname(bookList.get(k).
                                        getAuthor_surname());
                                try {
                                    loan.setIsbn(bookList.get(k).getIsbn());
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                                loan.setMaxLoan(bookList.get(k).getMaxLoan());
                                loan.setOnLoan(bookList.get(k).getOnLoan());
                                loan.setAvailable(bookList.get(k).
                                        getAvailable());
                                loan.setSignature(loans[j*3+1]);
                                loan.setTimestamp(loans[j*3+2]);
                                /* ...then add each one to the "listOfloans"
                                 * ArrayList.*/
                                listOfloans.add(loan);
                            }
                        }
                    }
                    /* if the "listOfloans" ArrayList is not empty, 
                     * add the loan to loanList with User as Key.*/
                    if (!listOfloans.isEmpty()) {
                        loanList.put(aUser, listOfloans);
                    }
                    // if the new user has any returned loans...
                    for (int j = 0; j < aUser.getReturns(); j++) {
                        for (int k = 1; k < bookList.size()+1; k++) {
                            /* ... find the "Book" object with the
                             * corresponding ISBN...*/
                            if(bookList.get(k).getIsbn().equals(returns[j*4])){
                                // ...then create a new loan object for each...
                                Loan loan = new Loan();
                                // ...and set the variables of each loan...
                                loan.setTitle(bookList.get(k).getTitle());
                                loan.setAuthor_firstname(bookList.get(k).
                                        getAuthor_firstname());
                                loan.setAuthor_surname(bookList.get(k).
                                        getAuthor_surname());
                                try {
                                    loan.setIsbn(bookList.get(k).getIsbn());
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                                loan.setMaxLoan(bookList.get(k).getMaxLoan());
                                loan.setOnLoan(bookList.get(k).getOnLoan());
                                loan.setAvailable(bookList.get(k)
                                        .getAvailable());
                                loan.setSignature(returns[j*4+1]);
                                loan.setTimestamp(returns[j*4+2]);
                                loan.setReturndate(returns[j*4+3]);
                                /* ...then add each one to the "listOfreturns"
                                 * ArrayList.*/
                                listOfreturns.add(loan);
                            }
                        }
                    }
                    /* if the "listOfreturns" ArrayList is not empty, 
                     * add the returned loan to returnList with User as Key.*/
                    if (!listOfreturns.isEmpty()) {
                        returnList.put(aUser, listOfreturns);   
                    }
                }
            }
            // tries to read the next line and interpret it as a String.
            try {
                line=reader.readLine();
            }
            // Catches IOexception if any is thrown when trying to read line.
            catch (IOException e) {
                e.printStackTrace();
            }
        }
        // try to close the BufferedReader.
        try {
            reader.close();
        }
        // Catches IOexception if any is thrown when trying to close.
        catch (IOException e) {
            e.printStackTrace();
        }
    }
    

    这是 Book 对象的实例化以及对象和方法是静态的问题。我不得不重写一些幕后的方法,这些方法是主要问题。感谢所有的帮助! =)

    【讨论】:

      猜你喜欢
      • 2023-03-15
      • 2021-10-01
      • 2016-03-27
      • 2021-09-14
      • 2014-02-25
      • 2018-07-19
      • 2017-06-21
      • 2018-06-22
      • 1970-01-01
      相关资源
      最近更新 更多