关于类里面静态变量,静态块,静态方法,静态main方法的执行顺序问题!

时间:2021-02-27 16:50:11
public class Example
{
    static final String A;
    static final String B;
    
    static{
        A="ab";
        B="cd";
    }

    public static void main(String[] args)
    {
        String C=A+B;
        String D="ab"+"cd";
        System.out.println(C);
        System.out.println(C==D);
    }
}

14 个解决方案

#1


public class Example
{
    static final String A="ab";
    static final String B="cd";
    
//    static{
//        A="ab";
//        B="cd";
//    }

    public static void main(String[] args)
    {
        String C=A+B;
        String D="ab"+"cd";
        System.out.println(C);
        System.out.println(C==D);
    }
}

#2


为什么会出现这种差异?求指教!

#3


难道第一种写法把A和B当成了变量,第二种写法A和B是常量?
应该用堆和栈来说明吧,等大神来指教吧

#4


引用 3 楼 a470577391 的回复:
难道第一种写法把A和B当成了变量,第二种写法A和B是常量?
应该用堆和栈来说明吧,等大神来指教吧
已经4颗了还成不了大神?

#5


引用 4 楼 ganshenml 的回复:
Quote: 引用 3 楼 a470577391 的回复:

难道第一种写法把A和B当成了变量,第二种写法A和B是常量?
应该用堆和栈来说明吧,等大神来指教吧
已经4颗了还成不了大神?

这个等级不代表实力啊,我就一菜鸟,灌水灌多了,分就高了,还没人回答啊

#6


引用 5 楼 a470577391 的回复:
Quote: 引用 4 楼 ganshenml 的回复:

Quote: 引用 3 楼 a470577391 的回复:

难道第一种写法把A和B当成了变量,第二种写法A和B是常量?
应该用堆和栈来说明吧,等大神来指教吧
已经4颗了还成不了大神?

这个等级不代表实力啊,我就一菜鸟,灌水灌多了,分就高了,还没人回答啊
原来如此,长知识了,哈哈!

#7


个人理解
1楼的代码中,在静态块中初始化静态变量,
static{
        A="ab";
        B="cd";
    }

相当于,static final String A;  A在栈区,初始化A="ab";后字符串常量"ab"在堆区,A指向"ab"的地址,B与此相同。String C=A+B;此时C指向堆内"abcd"的地址;String D="ab"+"cd";这句相当于
String D;
String str = new String("abcd");
D = str;
而new String("abcd"),在堆内已经有该字符串存在则D也指向该字符串,所以C==D返回true;

2楼代码,两个静态变量A、B都存在与方法区,C指向方法区的地址,而D指向堆内地址,所以C==D返回false

不知道理解的对不对

#8


引用 7 楼 Flying55555 的回复:
个人理解
1楼的代码中,在静态块中初始化静态变量,
static{
        A="ab";
        B="cd";
    }

相当于,static final String A;  A在栈区,初始化A="ab";后字符串常量"ab"在堆区,A指向"ab"的地址,B与此相同。String C=A+B;此时C指向堆内"abcd"的地址;String D="ab"+"cd";这句相当于
String D;
String str = new String("abcd");
D = str;
而new String("abcd"),在堆内已经有该字符串存在则D也指向该字符串,所以C==D返回true;

2楼代码,两个静态变量A、B都存在与方法区,C指向方法区的地址,而D指向堆内地址,所以C==D返回false

不知道理解的对不对
二楼代码是返回true的,而且层主有些问题搞错概念了!字符串常量不是放在堆区的,而是data segment!

#9


static  String A = "ab";
static  String B = "cd";

final 去掉也是false。

#10


引用 9 楼 rui888 的回复:
static  String A = "ab";
static  String B = "cd";

final 去掉也是false。
因为前面加上static那么就表示data segment中有了"ab"和"cd"字符串,后面操作的字符串常量也是存储在这个字符串常量池的,那么自然会相等!
如你所说,去掉static,虽然"ab"和"cd"也在常量池中有了,但是对应于后面的:
String C=A+B;
String D="ab"+"cd";
C生成的内容是堆区的,是没有在常量池中,自然为false。
尽管如此,那么不去掉static的前提下,层主如何解释该贴所提出的内容呢?

#11


是去掉 final  

#12


引用 10 楼 ganshenml 的回复:
Quote: 引用 9 楼 rui888 的回复:

static  String A = "ab";
static  String B = "cd";

final 去掉也是false。
因为前面加上static那么就表示data segment中有了"ab"和"cd"字符串,后面操作的字符串常量也是存储在这个字符串常量池的,那么自然会相等!
如你所说,去掉static,虽然"ab"和"cd"也在常量池中有了,但是对应于后面的:
String C=A+B;
String D="ab"+"cd";
C生成的内容是堆区的,是没有在常量池中,自然为false。
尽管如此,那么不去掉static的前提下,层主如何解释该贴所提出的内容呢?
补充一下,去掉static是会报错的,原因是static变量不能调用非static的变量!

#13


引用 11 楼 rui888 的回复:
是去掉 final  
那层主能给个解释不?我开始看错了,也解释错了,去掉static是编译错误的!

#14


引用 8 楼 ganshenml 的回复:
Quote: 引用 7 楼 Flying55555 的回复:

个人理解
1楼的代码中,在静态块中初始化静态变量,
static{
        A="ab";
        B="cd";
    }

相当于,static final String A;  A在栈区,初始化A="ab";后字符串常量"ab"在堆区,A指向"ab"的地址,B与此相同。String C=A+B;此时C指向堆内"abcd"的地址;String D="ab"+"cd";这句相当于
String D;
String str = new String("abcd");
D = str;
而new String("abcd"),在堆内已经有该字符串存在则D也指向该字符串,所以C==D返回true;

2楼代码,两个静态变量A、B都存在与方法区,C指向方法区的地址,而D指向堆内地址,所以C==D返回false

不知道理解的对不对
二楼代码是返回true的,而且层主有些问题搞错概念了!字符串常量不是放在堆区的,而是data segment!


又在网上查了下

1楼的代码
static{
        A="ab";
        B="cd";
    }

A="ab"; 等于 A=new String("ab");此时 A是引用对象,指向堆区的一个String对象(值为常量池的"ab");

String C=A+B;等于String C=(new StringBuilder()).append(A).append(B).toString(); C 也是指向堆区的一个String对象(值为常量池的"abcd")
String D="ab"+"cd"; 等于String D = "abcd";D也是指向堆区的一个String对象(值为常量池的"abcd")
所以C==D返回false(C是堆内的一个String对象,D是另外一个String对象,但是C和D不是一个对象!)


2楼代码
A、B直接指向常量池的两个字符串常量(不是堆内对象)
String C=A+B;等于String C="ab"+"cd";
所以和D相等,都指向常量池的"abcd"常量!

2楼的代码改成static final String A=new String("ab"); 或者String D="ab"+"cd";改成String D=new String("ab")+new String("cd");这样C==D返回false

总的来说静态常量直接赋值的话不会在堆内生成对象,在静态块初始化会在堆内生成对象!

#1


public class Example
{
    static final String A="ab";
    static final String B="cd";
    
//    static{
//        A="ab";
//        B="cd";
//    }

    public static void main(String[] args)
    {
        String C=A+B;
        String D="ab"+"cd";
        System.out.println(C);
        System.out.println(C==D);
    }
}

#2


为什么会出现这种差异?求指教!

#3


难道第一种写法把A和B当成了变量,第二种写法A和B是常量?
应该用堆和栈来说明吧,等大神来指教吧

#4


引用 3 楼 a470577391 的回复:
难道第一种写法把A和B当成了变量,第二种写法A和B是常量?
应该用堆和栈来说明吧,等大神来指教吧
已经4颗了还成不了大神?

#5


引用 4 楼 ganshenml 的回复:
Quote: 引用 3 楼 a470577391 的回复:

难道第一种写法把A和B当成了变量,第二种写法A和B是常量?
应该用堆和栈来说明吧,等大神来指教吧
已经4颗了还成不了大神?

这个等级不代表实力啊,我就一菜鸟,灌水灌多了,分就高了,还没人回答啊

#6


引用 5 楼 a470577391 的回复:
Quote: 引用 4 楼 ganshenml 的回复:

Quote: 引用 3 楼 a470577391 的回复:

难道第一种写法把A和B当成了变量,第二种写法A和B是常量?
应该用堆和栈来说明吧,等大神来指教吧
已经4颗了还成不了大神?

这个等级不代表实力啊,我就一菜鸟,灌水灌多了,分就高了,还没人回答啊
原来如此,长知识了,哈哈!

#7


个人理解
1楼的代码中,在静态块中初始化静态变量,
static{
        A="ab";
        B="cd";
    }

相当于,static final String A;  A在栈区,初始化A="ab";后字符串常量"ab"在堆区,A指向"ab"的地址,B与此相同。String C=A+B;此时C指向堆内"abcd"的地址;String D="ab"+"cd";这句相当于
String D;
String str = new String("abcd");
D = str;
而new String("abcd"),在堆内已经有该字符串存在则D也指向该字符串,所以C==D返回true;

2楼代码,两个静态变量A、B都存在与方法区,C指向方法区的地址,而D指向堆内地址,所以C==D返回false

不知道理解的对不对

#8


引用 7 楼 Flying55555 的回复:
个人理解
1楼的代码中,在静态块中初始化静态变量,
static{
        A="ab";
        B="cd";
    }

相当于,static final String A;  A在栈区,初始化A="ab";后字符串常量"ab"在堆区,A指向"ab"的地址,B与此相同。String C=A+B;此时C指向堆内"abcd"的地址;String D="ab"+"cd";这句相当于
String D;
String str = new String("abcd");
D = str;
而new String("abcd"),在堆内已经有该字符串存在则D也指向该字符串,所以C==D返回true;

2楼代码,两个静态变量A、B都存在与方法区,C指向方法区的地址,而D指向堆内地址,所以C==D返回false

不知道理解的对不对
二楼代码是返回true的,而且层主有些问题搞错概念了!字符串常量不是放在堆区的,而是data segment!

#9


static  String A = "ab";
static  String B = "cd";

final 去掉也是false。

#10


引用 9 楼 rui888 的回复:
static  String A = "ab";
static  String B = "cd";

final 去掉也是false。
因为前面加上static那么就表示data segment中有了"ab"和"cd"字符串,后面操作的字符串常量也是存储在这个字符串常量池的,那么自然会相等!
如你所说,去掉static,虽然"ab"和"cd"也在常量池中有了,但是对应于后面的:
String C=A+B;
String D="ab"+"cd";
C生成的内容是堆区的,是没有在常量池中,自然为false。
尽管如此,那么不去掉static的前提下,层主如何解释该贴所提出的内容呢?

#11


是去掉 final  

#12


引用 10 楼 ganshenml 的回复:
Quote: 引用 9 楼 rui888 的回复:

static  String A = "ab";
static  String B = "cd";

final 去掉也是false。
因为前面加上static那么就表示data segment中有了"ab"和"cd"字符串,后面操作的字符串常量也是存储在这个字符串常量池的,那么自然会相等!
如你所说,去掉static,虽然"ab"和"cd"也在常量池中有了,但是对应于后面的:
String C=A+B;
String D="ab"+"cd";
C生成的内容是堆区的,是没有在常量池中,自然为false。
尽管如此,那么不去掉static的前提下,层主如何解释该贴所提出的内容呢?
补充一下,去掉static是会报错的,原因是static变量不能调用非static的变量!

#13


引用 11 楼 rui888 的回复:
是去掉 final  
那层主能给个解释不?我开始看错了,也解释错了,去掉static是编译错误的!

#14


引用 8 楼 ganshenml 的回复:
Quote: 引用 7 楼 Flying55555 的回复:

个人理解
1楼的代码中,在静态块中初始化静态变量,
static{
        A="ab";
        B="cd";
    }

相当于,static final String A;  A在栈区,初始化A="ab";后字符串常量"ab"在堆区,A指向"ab"的地址,B与此相同。String C=A+B;此时C指向堆内"abcd"的地址;String D="ab"+"cd";这句相当于
String D;
String str = new String("abcd");
D = str;
而new String("abcd"),在堆内已经有该字符串存在则D也指向该字符串,所以C==D返回true;

2楼代码,两个静态变量A、B都存在与方法区,C指向方法区的地址,而D指向堆内地址,所以C==D返回false

不知道理解的对不对
二楼代码是返回true的,而且层主有些问题搞错概念了!字符串常量不是放在堆区的,而是data segment!


又在网上查了下

1楼的代码
static{
        A="ab";
        B="cd";
    }

A="ab"; 等于 A=new String("ab");此时 A是引用对象,指向堆区的一个String对象(值为常量池的"ab");

String C=A+B;等于String C=(new StringBuilder()).append(A).append(B).toString(); C 也是指向堆区的一个String对象(值为常量池的"abcd")
String D="ab"+"cd"; 等于String D = "abcd";D也是指向堆区的一个String对象(值为常量池的"abcd")
所以C==D返回false(C是堆内的一个String对象,D是另外一个String对象,但是C和D不是一个对象!)


2楼代码
A、B直接指向常量池的两个字符串常量(不是堆内对象)
String C=A+B;等于String C="ab"+"cd";
所以和D相等,都指向常量池的"abcd"常量!

2楼的代码改成static final String A=new String("ab"); 或者String D="ab"+"cd";改成String D=new String("ab")+new String("cd");这样C==D返回false

总的来说静态常量直接赋值的话不会在堆内生成对象,在静态块初始化会在堆内生成对象!