难以理解Java中的静态

时间:2015-11-16 17:39:24

标签: java static

Class Stat1.java

package Static;

import java.util.ArrayList;
import java.util.Locale.Category;
import java.util.TreeSet;

public class Stat1 {
    static TreeSet<String> category= new TreeSet<>();;

    public static void main(String[]args){
        Stat1 s0 = new Stat1();
        s0.category.add("Pocket Money");
        s0.category.add("Salary");
        Stat1 s = new Stat1();
        s.category.add("Mother");
        s.print_Category();

        Stat1 s1 = new Stat1();
        s1.category.add("Father");
        s1.category.add("aaaaaaaa");
        Stat1.category.add("999");
        s1.print_Category();

    }

    public static void print_Category(){
        System.out.println(category);
    }
}

当我运行上面的类时,输出是 -

[Mother, Pocket Money, Salary]
[999, Father, Mother, Pocket Money, Salary, aaaaaaaa]

Class Stat2.java

package Static;
import Static.Stat1;
public class Stat2 {
    public static void main(String[]args){

        Stat1 s = new Stat1();

        s.category.add("brother");
        System.out.println(s.category);


    }
}

输出是:
[brother]
现在根据我的理解当我们使用static关键字时,每个对象共享该实例的相同副本,这在Stat1.java类中很明显。但是在Stat2.java中输出只显示添加的String仅限该类中的TreeSet。 据我说,输出应该包含添加到TreeSet的所有元素。 请解释做错了什么。 在此先感谢!

3 个答案:

答案 0 :(得分:4)

  

输出应包含添加到TreeSet的所有元素。

我假设你期望 Stat1和Stat2的输出是这样的:

$ java -cp . Stat1
[Mother, Pocket Money, Salary]
[999, Father, Mother, Pocket Money, Salary, aaaaaaaa]

$ java -cp . Stat2
[999, Father, Mother, Pocket Money, Salary, aaaaaaaa, brother]
                                                      ^^^^^^^ 
    "brother" included after running Stat1 then Stat2 |

您在运行Stat2后只看到brother的原因是因为您正在开始一个全新的流程。 static关键字仅影响单个流程中数据的共享方式

例如,如果文件myprog.jar中有一个java程序,并且运行了两次

java -jar myprog.jar &
java -jar myprog.jar

然后这些命令中的每一个都启动一个新进程。即使它们是与相同类运行的相同程序,它们共享内存,因此它们 >分享任何类的实例。即使myprog.jar在类中使用静态字段,这些类也不知道彼此。

(那么static实际上为你做了什么?Here是一个简单的,以示例为导向的描述。)

解决方案:如果您希望跨不同进程共享数据,则需要读取和写入数据库或文件,以便在进程终止后数据存在。这称为persistence

理论:如果您想了解更多关于数据库和文件在以这种方式使用时为您的程序所做的事情,请阅读inter-process communicantion

高级:如果要在不同进程之间使用“相同”对象(即具有相同数据的对象),请了解object relational mapping,这是一种自动使用文件的技术/ databases来跨进程同步对象。但是我建议在尝试任何这些之前用java和文件练​​习更多。

答案 1 :(得分:1)

你在这里误解了一些事情。

首先,static关键字适用于多种情境,但让我们关注您的情况。如果它附加到字段,则该字段的值在类的实例之间共享。换句话说,如果您有一个类的多个实例,那么这些实例都将引用相同的字段。

这是您在第一个案例中展示的场景;由于您创建了多个Stat1实例,因此每个实例都具有相同的TreeSet,这就是您在第二次打印时看到更多值添加的原因。

这也是 为什么你在第二个例子中没有看到相同的行为。由于您只创建了{em>一个的Stat1实例,因此静态变量只保存一个值。

您一次只执行一个程序(这意味着您一次只执行一个这些案例),所以您希望在第二个类中看到的行为赢了除非您在Stat1内实例化更多Stat2个类,否则不会实现。

答案 2 :(得分:1)

当你运行第二课时,java首先不知道什么。 如果您在第二课中写s.main(null);,则所有字符串都将出现在集合中。