【问题标题】:Does the static keyword prevent new objects from being assigned to the variable? [closed]static 关键字是否会阻止将新对象分配给变量? [关闭]
【发布时间】:2015-03-19 16:29:12
【问题描述】:

给定下面的代码:

class Demo {                    
    static String s = "123";    

    static void m1(String s) {
        this.s = s;             
    }

    void m2(String s) {
        this.s = s;              
    }
}

class Hello {
    public static void main(String args) {
        Demo.m1("456");          
        Demo d = new Demo();       
        d.m2("789");         
    }
 }

我想知道在创建对象方面使用实例变量和静态变量有什么区别:

  1. 假设字符串是不可变的,变量 s 是静态的,那么为变量 s 创建了多少个对象?

  2. 调用m1()等静态方法时是否创建了新对象?

  3. 调用m2()等实例方法时是否创建了新对象?


已编辑:

我对静态关键字有一个错误的假设。现在我清楚了。

  1. static 是关键字。
  2. 用于声明类的成员。
  3. 静态成员属于类。
  4. 实例变量不能在静态上下文中使用。
  5. 此关键字不能在静态上下文中使用。
  6. 无需创建对象即可访问静态成员。
  7. 当类加载到内存中时,静态变量就会生效。
  8. 此关键字只能用于访问实例成员。
  9. 此关键字用于访问同一类中的类成员。

感谢您的帮助。以下是修改后的代码:

class Demo {                    
    static String s= "123";  //Static variable
    String s1 ="abc"; // Instance variable  

    static void m1(String s) {
        Demo.s = s; //Accessing an static variable       
    }

    void m2(String s,String s1) {
        Demo.s = s; 
        this.s1 = s1;//Accessing an instance variable           
    }
}

class Hello {
    public static void main(String args[]) {
        Demo.m1("456");          
        Demo d = new Demo();       
        d.m2("789","xyz");         
    }
}

【问题讨论】:

  • 您个人如何看待这个问题?
  • 我对静态变量有点困惑。如果它是一个实例变量,那么就会创建新对象。因为字符串是不可变的。
  • 请记住:s 不是 String 对象的实例 - 它是一个变量。在 Java 中,变量是对对象实例的引用,而不是实例本身。 "123" 是一个字符串字面量,它代表一个 String 对象的实例。 s="123" 将引用 s 设置为指向包含字符 1,2 和 3 的字符串实例。

标签: java memory-management static static-methods static-members


【解决方案1】:

static 修饰符仅表示变量是类的成员,而不是特定实例的成员。它与是否正在创建新对象无关。

首先对您的代码进行一些观察:

方法m1()

static void m1(String s) {
    this.s = s;
}

这不会编译,因为您不能从静态方法中引用实例变量。应该是:

static void m1(String s) {
    Demo.s = s;
}

方法m2()

void m2(String s) {
    this.s = s;
}

现在这不会给你一个编译错误,但应该给你一个警告。 this 应仅用于实例属性和方法。由于s 是一个类属性,你应该使用类名来代替:

void m2(String s) {
    Demo.s = s;
}

现在我们可以对代码进行推理了:

  1. 当你做static String s = "123"时,你会创建一个新的String并让s指向它,所以s -> "123"

  2. 当你调用Demo.m1("456")时,你创建了另一个String,这次"456",并让s指向它,所以s -> "456"

  3. 当你调用d.m2("789")时,你再次创建了一个String对象"789",并让s指向它,所以s -> "789"

因此,您总共创建了 3 个String 对象。

【讨论】:

  • 谢谢...调用 m1() 方法和调用 m2() 有什么区别..
  • 我在更新的答案中建议对方法 m1() 和 m2() 进行一些更正。鉴于这些变化,两种方法的效果应该是相同的。唯一的区别是你需要一个 Demo 实例来调用 m2()。
  • 所以创建静态方法没有优势...静态方法和静态变量存储在哪里..???
  • 当您需要存储和处理与类相关但不与任何特定实例相关的信息时,应创建静态方法和变量。有关静态成员的进一步阅读和示例,您可以查看文档:docs.oracle.com/javase/tutorial/java/javaOO/classvars.html
  • 最后一个问题——一个对象是一个类的一个实例" ...你能详细说明一下吗...实例和对象的区别..
【解决方案2】:

只创建一个静态 String (这是静态背后的基本思想)。因此,通过调用 Demo.m1("353"),您将 s 更改为“353”,并通过创建一个新的 Demo d,并调用 d.m2("344"),您将用“344”覆盖内容“353”。

我对这个问题有点困惑,因为您可以使用

轻松地自己测试它
public void talk(){
    System.out.println("my static string s is: "+s)
}

并在程序的不同阶段打印 s。你想知道为什么会发生这种情况吗?

这可能会对您有所帮助: Immutability of Strings in Java

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-10
    • 2012-07-21
    • 1970-01-01
    • 2019-10-22
    • 2012-06-17
    • 2020-05-28
    • 1970-01-01
    相关资源
    最近更新 更多