Java字符串变量声明与赋值的常见面试题——完整剖析

简介: Java字符串变量声明与赋值的常见面试题——完整剖析

面试题目:

下列代码会创建几个对象?【不考虑常量池】

class Main{
  public static void main(String[] args){
    String a = "Hello ";
    String b = "World";
    String c = a + b ;
    System.out.println(c);
  }
}

String概述

java.lang.String类代表字符串,String类定义的变量可以用于指向字符串对象,然后操作该字符串。

Java程序中的所有字符串文字(例如:”abc“)都为此类的对象。

String类的特点详解

String其实常被称为不可变字符串类型,它的对象在创建后不能被更改。

我们使用javac编译器先编译成class文件,通过java进行运行,最后通过javap进行分析。

这里我们可以看到好多单词可以丢下哦下面的标准文档解释挨个看一下,我这里已经抽取出来了,一起来瞅瞅。

Main();的无参构造函数Code部分(任何一个类都有一个默认无参的构造函数)。

aload_0:将第 1 个 int 类型本地变量推送至栈顶。

invokespecial:调用父类方法、实例初始化方法、私有方法。

return:从当前方法返回void。

主函数main的Code部分:

ldc:将 int、 float 或 String 类型常量值从常量池中推送至栈顶。

astore_1:将栈顶 int 类型数值存入第 2 个本地变量。

new:创建一个对象,并将其引用值压入栈顶。

dup:复制栈顶数值并将复制值压入栈顶。

getstatic:获取指定类的静态字段,并将其值压入栈顶。

以上是出现在解释器中助记符解释,根据这些解释我们就能看懂差不多了。

       String a = "Hello ";// String Hello创建了一个对象

       String b = "World";// String World创建了第二个对象

       String c = a + b ;//首先c变量单独获取一个地址,因为是【new】,所以是但三个对象,后来因为可以看到【// Method java/lang/StringBuilder."<init>":()V】代表实例化,这里又是一个对象,现在是第四个。字符串的累加使用到了【Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;】这个append步骤是没有增加对象的。在【#7】的步骤中【// Method java/lang/StringBuilder.toString:()Ljava/lang/String;】没有创建新对象,因为toString源码如下:

public String toString() {
    return this;
}

到这里是4个对象。

       System.out.println(c); // Field java/lang/System.out:Ljava/io/PrintStream;因为使用到了PrintStream所以会再次创建一个对象,【#9】使用的是PrintStream自带的函数,故而无需创建对象,最终创建了【5】个对象。

助记符对照表

我们来看看标准文档解释,所有的助记符都有对应的连接可以进行具体查看。

分类 操作码 帮助记符 指令含义

常量

0

0x00

nop

什么都不做

1

0x01

aconst_null

将 null 推送至栈顶

2

0x02

iconst_m1

将 int 类型 -1 推送至栈顶

3

0x03

iconst_0

将 int 类型 0 推送至栈顶

4

0x04

iconst_1

将 int 类型 1 推送至栈顶

5

0x05

iconst_2

将 int 类型 2 推送至栈顶

6

0x06

iconst_3

将 int 类型 3 推送至栈顶

7

0x07

iconst_4

将 int 类型 4 推送至栈顶

8

0x08

iconst_5

将 int 类型 5 推送至栈顶

9

0x09

lconst_0

将 long 类型 0 推送至栈顶

10

0x0a

lconst_1

将 long 类型 1 推送至栈顶

11

0x0b

fconst_0

将 float 类型 0 推送至栈顶

12

0x0c

fconst_1

将 float 类型 1 推送至栈顶

13

0x0d

fconst_2

将 float 类型 2 推送至栈顶

14

0x0e

dconst_0

将 double 类型 0 推送至栈顶

15

0x0f

dconst_1

将 double 类型 1 推送至栈顶

16

0x10

bipush

将单字节的常量值(-128 ~ 127)推送至栈顶

17

0x11

sipush

将一个短整类型常量值(-32,768 ~ 32,767)推送栈顶

18

0x12

ldc

将 int、 float 或 String 类型常量值从常量池中推送至栈顶

19

0x13

ldc_w

将int、 float 或 String 类型常量值从常量池中推送栈顶(宽索引)

20

0x14

ldc2_w

将 long 或 double 类型常量值从常量池中推送至栈(宽索引)

加载

21

0x15

iload

将指定的 int 类型本地变量推送至栈顶

22

0x16

lload

将指定的 long 类型本地变量推送至栈顶

23

0x17

fload

将指定的 float 类型本地变量推送至栈顶

24

0x18

dload

将指定的 double 类型本地变量推送至栈顶

25

0x19

aload

将指定的引用类型本地变量推送至栈顶

26

0x1a

iload_0

将第 1 个 int 类型本地变量推送至栈顶

27

0x1b

iload_1

将第 2 个 int 类型本地变量推送至栈顶

28

0x1c

iload_2

将第 3 个 int 类型本地变量推送至栈顶

29

0x1d

iload_3

将第 4 个 int 类型本地变量推送至栈顶

30

0x1e

lload_0

将第 1 个 long 类型本地变量推送至栈顶

31

0x1f

lload_1

将第 2 个 long 类型本地变量推送至栈顶

32

0x20

lload_2

将第 3 个 long 类型本地变量推送至栈顶

33

0x21

lload_3

将第 4 个 long 类型本地变量推送至栈顶

34

0x22

fload_0

将第 1 个 float 类型本地变量推送至栈顶

35

0x23

fload_1

将第 2 个 float 类型本地变量推送至栈顶

36

0x24

fload_2

将第 3 个 float 类型本地变量推送至栈顶

37

0x25

fload_3

将第 4 个 float 类型本地变量推送至栈顶

38

0x26

dload_0

将第 1 个 double 类型本地变量推送至栈顶

39

0x27

dload_1

将第 2 个 double 类型本地变量推送至栈顶

40

0x28

dload_2

将第 3 个 double 类型本地变量推送至栈顶

41

0x29

dload_3

将第 4 个 double 类型本地变量推送至栈顶

42

0x2a

aload_0

将第 1 个引用类型本地变量推送至栈顶

43

0x2b

aload_1

将第 2 个引用类型本地变量推送至栈顶

44

0x2c

aload_2

将第 3 个引用类型本地变量推送至栈顶

45

0x2d

aload_3

将第 4 个引用类型本地变量推送至栈顶

46

0x2e

iaload

将 int 类型数组的指定元素推送至栈顶

47

0x2f

laload

将 long 类型数组的指定元素推送至栈顶

48

0x30

faload

将 float 类型数组的指定元素推送至栈顶

49

0x31

daload

将 double 类型数组的指定元素推送至栈顶

50

0x32

aaload

将引用类型数组的指定元素推送至栈顶

51

0x33

baload

将 boolean 或 byte 类型数组的指定元素推送至栈顶

52

0x34

caload

将 char 类型数组的指定元素推送至栈顶

53

0x35

saload

将 short 类型数组的指定元素推送至栈顶

存储

54

0x36

istore

将栈顶 int 类型数值存入指定本地变量

55

0x37

lstore

将栈顶 long 类型数值存入指定本地变量

56

0x38

fstore

将栈顶 float 类型数值存入指定本地变量

57

0x39

dstore

将栈顶 double 类型数值存入指定本地变量

58

0x3a

astore

将栈顶引用类型数值存入指定本地变量

59

0x3b

istore_0

将栈顶 int 类型数值存入第 1 个本地变量

60

0x3c

istore_1

将栈顶 int 类型数值存入第 2 个本地变量

61

0x3d

istore_2

将栈顶 int 类型数值存入第 3 个本地变量

62

0x3e

istore_3

将栈顶 int 类型数值存入第 4 个本地变量

63

0x3f

lstore_0

将栈顶 long 类型数值存入第 1 个本地变量

64

0x40

lstore_1

将栈顶 long 类型数值存入第 2 个本地变量

65

0x41

lstore_2

将栈顶 long 类型数值存入第 3 个本地变量

66

0x42

lstore_3

将栈顶 long 类型数值存入第 4 个本地变量

67

0x43

fstore_0

将栈顶 float 类型数值存入第 1 个本地变量

68

0x44

fstore_1

将栈顶 float 类型数值存入第 2 个本地变量

69

0x45

fstore_2

将栈顶 float 类型数值存入第 3 个本地变量

70

0x46

fstore_3

将栈顶 float 类型数值存入第 4 个本地变量

71

0x47

dstore_0

将栈顶 double 类型数值存入第 1 个本地变量

72

0x48

dstore_1

将栈顶 double 类型数值存入第 2 个本地变量

73

0x49

dstore_2

将栈顶 double 类型数值存入第 3 个本地变量

74

0x4a

dstore_3

将栈顶 double 类型数值存入第 4 个本地变量

75

0x4b

astore_0

将栈顶引用类型数值存入第 1 个本地变量

76

0x4c

astore_1

将栈顶引用类型数值存入第 2 个本地变量

77

0x4d

astore_2

将栈顶引用类型数值存入第 3 个本地变量

78

0x4e

astore_3

将栈顶引用类型数值存入第 4 个本地变量

79

0x4f

iastore

将栈顶 int 类型数值存入指定数组的指定索引位置

80

0x50

lastore

将栈顶 long 类型数值存入指定数组的指定索引位置

81

0x51

fastore

将栈顶 float 类型数值存入指定数组的指定索引位置

82

0x52

dastore

将栈顶 double 类型数值存入指定数组的指定索引位置

83

0x53

aastore

将栈顶引用类型数值存入指定数组的指定索引位置

84

0x54

bastore

将栈顶 boolean 或 byte 类型数值存入指定数组的指定索引位置

85

0x55

castore

将栈顶 char 类型数值存入指定数组的指定索引位置

86

0x56

sastore

将栈顶 short 类型数值存入指定数组的指定索引位置

87

0x57

pop

将栈顶数值弹出(数值不能是 long 或 double 类型的)

88

0x58

pop2

将栈顶的一个 long 或 double 类型的数值或两个其他类型的数值弹出

89

0x59

dup

复制栈顶数值并将复制值压入栈顶

90

0x5a

dup_x1

复制栈顶值并将其插入栈顶那两个值的下面

91

0x5b

dup_x2

复制栈顶值并将其插入栈顶那两个或三个值的下面

92

0x5c

dup2

复制栈顶的一个 long 或 double 类型的值,或两个其他类型的值,并将其压入栈顶

93

0x5d

dup2_x1

复制栈顶的一个或两个值,并将其插入栈顶那两个或三个值的下面

94

0x5e

dup2_x2

复制栈顶的一个或两个值,并将其插入栈顶那两个、三个或四个值的下面

95

0x5f

swap

将栈顶的两个数值互换(数值不能是 long 或 double 类型的)

数学

96

0x60

iadd

将栈顶两 int 类型数值相加并将结果压入栈顶

97

0x61

ladd

将栈顶两 1ong 类型数值相加并将结果压入栈顶

98

0x62

fadd

将栈顶两 float 类型数值相加并将结果压入栈顶

99

0x63

dadd

将栈顶两 double 类型数值相加并将结果压入栈顶

100

0x64

isub

将栈顶两 int 类型数值相减并将结果压入栈顶

101

0x65

lsub

将栈顶两 long 类型数值相减并将结果压入栈顶

102

0x66

fsub

将栈顶两 float 类型数值相减并将结果压入栈顶

103

0x67

dsub

将栈顶两 double 类型数值相减并将结果压入栈顶

104

0x68

imul

将栈顶两 int 类型数值相乘并将结果压入栈顶

105

0x69

lmul

将栈顶两 long 类型数值相乘并将结果压入栈顶

106

0x6a

fmul

将栈顶两 float 类型数值相乘并将结果压入栈顶

107

0x6b

dmul

将栈顶两 double 类型数值相乘并将结果压入栈顶

108

0x6с

idiv

将栈顶两 int 类型数值相除并将结果压入栈顶

109

0x6d

ldiv

将栈顶两 long 类型数值相除并将结果压入栈顶

110

0x6e

fdiv

将栈顶两 float 类型数值相除并将结果压入栈顶

111

0x6f

ddiv

将栈顶两 double 类型数值相除并将结果压入栈顶

112

0x70

irem

将栈顶两 int 类型数值作取模运算并将结果压入栈顶

113

0x71

lrem

将栈顶两 long 类型数值作取模运算并将结果压入栈顶

114

0x72

frem

将栈顶两 float 类型数值作取模运算并将结果压入栈顶

115

0x73

drem

将栈顶两 double 类型数值作取模运算并将结果压入栈顶

116

0x74

ineg

将栈顶 int 类型数值取负并将结果压入栈顶

117

0x75

lneg

将栈顶 long 类型数值取负并将结果压入栈顶

118

0x76

fneg

将栈顶 float 类型数值取负并将结果压入栈顶

119

0x77

dneg

将栈顶 double 类型数值取负并将结果压入栈顶

120

0x78

ishl

将 int 类型数值左移位指定位数并将结果压入栈顶

121

0x79

lshl

将 long 类型数值左移位指定位数并将结果压入栈顶

122

0x7a

ishr

将 int 类型数值(有符号)右移位指定位数并将结果压入栈顶

123

0x7b

lshr

将 long 类型数值(有符号)右移位指定位数并将结果压入栈顶

124

0x7c

iushr

将 int 类型数值(无符号)右移位指定位数并将结果压入栈顶

125

0x7d

lushr

将 long 类型数值(无符号)右移位指定位数并将结果压入栈顶

126

0x7e

iand

将栈顶两 int 类型数值作“按位与”并将结果压入栈顶

127

0x7f

land

将栈顶两 long 类型数值作“按位与”并将结果压入栈顶

128

0x80

ior

将栈顶两 int 类型数值作“按位或”并将结果压入栈顶

129

0x81

lor

将栈顶两 long 类型数值作“按位或”并将结果压入栈顶

130

0x82

ixor

将栈顶两 int 类型数值作“按位异或”并将结果压入栈顶

131

0x83

lxor

将栈顶两 long 类型数值作“按位异或”并将结果压入栈顶

132

0x84

iinc

将指定 int 类型变量增加指定值(i++i--i += 2)

转换

133

0x85

i2l

将栈顶 int 类型数值强制转换成 long 类型数值并将结果压入栈顶

134

0x86

i2f

将栈顶 int 类型数值强制转换成 float 类型数值并将结果压入栈顶

135

0x87

i2d

将栈顶 int 类型数值强制转换成 double 类型数值并将结果压入栈顶

136

0x88

l2i

将栈顶 long 类型数值强制转换成 int 类型数值并将结果压入栈顶

137

0x89

l2f

将栈顶 long 类型数值强制转换成 float 类型数值并将结果压入栈顶

138

0x8a

l2d

将栈顶 long 类型数值强制转换成 double 类型数值并将结果压入栈顶

139

0x8b

f2i

将栈顶 float 类型数值强制转换成 int 类型数值并将结果压入栈顶

140

0x8c

f2l

将栈顶 float 类型数值强制转换成 long 类型数值并将结果压入栈顶

141

0x8d

f2d

将栈顶 float 类型数值强制转换成 double 类型数值并将结果压入栈顶

142

0x8e

d2i

将栈顶 double 类型数值强制转换成 int 类型数值并将结果压入栈顶

143

0x8f

d2l

将栈顶 double 类型数值强制转换成 long 类型数值并将结果压入栈顶

144

0x90

d2f

将栈顶 double 类型数值强制转换成 float 类型数值并将结果压入栈顶

145

0x91

i2b

将栈顶 int 类型数值强制转换成 byte 类型数值并将结果压入栈顶

146

0x92

i2c

将栈顶 int 类型数值强制转换成 char 类型数值并将结果压入栈顶

147

0x93

i2s

将栈顶 int 类型数值强制转换成 short 类型数值并将结果压入栈顶

比较

148

0x94

lcmp

比较栈顶两 long 类型数值大小,并将结果(1,0,-1)压入栈顶

149

0x95

fcmpl

比较栈顶两 float 类型数值大小,并将结果(1,0,-1)压入栈顶;当其中一个数值为“NaN”时,将 -1 压入栈顶

150

0x96

fcmpg

比较栈顶两 float 类型数值大小,并将结果(1,0,-1)压入栈顶;当其中一个数值为“NaN”时,将1压入栈顶

151

0x97

dcmpl

比较栈顶两 double 类型数值大小,并将结果(1,0,-1)压入栈顶;当其中一个数值为“NaN”时,将-1压入栈顶

152

0x98

dcmpg

比较栈顶两 double 类型数值大小,并将结果(1,0,-1)压入栈顶;当其中一个数值为“NaN”时,将1压入栈顶

153

0x99

ifeq

当栈顶 int 类型数值等于 0 时跳转

154

0x9a

ifne

当栈顶 int 类型数值不等于 0 时跳转

155

0x9b

iflt

当栈顶 int 类型数值小于 0 时跳转

156

0x9c

ifge

当栈顶 int 类型数值大于等于 0 时跳转

157

0x9d

ifgt

当栈顶 int 类型数值大于 0 时跳转

158

0x9e

ifle

当栈顶 int 类型数值小于等于 0 时跳转

159

0x9f

if_icmpeq

比较栈顶两 int 类型数值大小,当前者等于后者时跳转

160

0xa0

if_icmpne

比较栈顶两 int 类型数值大小,当前者不等于后者时跳转

161

0xa1

if_icmplt

比较栈顶两 int 类型数值大小,当前者小于后者时跳转

162

0xa2

if_icmpge

比较栈顶两 int 类型数值大小,当前者大于等于后者时跳转

163

0xa3

if_icmpgt

比较栈顶两 int 类型数值大小,当前者大于后者时跳转

164

0xa4

if_icmple

比较栈顶两 int 类型数值大小,当前者小于等于后者时跳转

165

0xa5

if_acmpeq

比较栈顶两引用类型数值,当结果相等时跳转

166

0xa6

ifacmpne

比较栈顶两引用类型数值,当结果不相等时跳转

控制

167

0xa7

goto

无条件跳转

168

0xa8

jsr

跳转至指定 16 位 offset 位置,并将 jsr 下一条指令地址压入栈顶

169

0xa9

ret

返回至由指定的局部变量所给出的指令位置(一般与 jsr、jsr_w 联合使用)

170

0xaa

tableswitch

用于 switch 条件跳转,case 值连续(变长指令)

171

0xab

lookupswitch

用于 switch 条件跳转,case 值不连续(变长指令)

172

0xac

ireturn

从当前方法返回 int

173

Oxad

lreturn

从当前方法返回 long

174

0xae

freturn

从当前方法返回 float

175

0xaf

dreturn

从当前方法返回 double

176

0xb0

areturn

从当前方法返回对象引用

177

0xb1

return

从当前方法返回void

引用

178

0xb2

getstatic

获取指定类的静态字段,并将其值压入栈顶

179

0xb3

putstatic

为指定类的静态字段赋值

180

0xb4

getfield

获取指定类的实例字段,并将其值压入栈顶

181

0xb5

putfield

为指定类的实例字段赋值

182

0xb6

invokevirtual

调用实例方法

183

0xb7

invokespecial

调用父类方法、实例初始化方法、私有方法

184

0xb8

invokestatic

调用静态方法

185

0xb9

invokeinterface

调用接口方法

186

0xba

invokedynamic

调用动态链接方法

187

0xbb

new

创建一个对象,并将其引用值压入栈顶

188

0xbc

newarray

创建一个指定原始类型(如int、float 、char等)的数组,并将其引用值压入栈顶

189

0xbd

anewarray

创建一个引用型(如类、接口、数组)的数组,并将其引用值压入栈顶

190

0xbe

arraylength

获得数组的长度值并压入栈顶

191

0xbf

athrow

将栈顶的异常抛出

192

0xcO

checkcast

检验类型转换,检验未通过将抛出 ClassCastException

193

0xc1

instanceof

检验对象是否是指定类的实例。如果是,就将 1 压入栈顶,否则将 0 压入栈顶

194

0xc2

monitorenter

获得对象的锁,用于实现同步块

195

0xc3

monitorexit

释放对象的锁,用于实现同步块

扩展

196

0xc4

wide

扩展本地变量索引的宽度

197

0xс5

multianewarray

创建指定类型和指定维度的多维数组(执行该指令时,操作栈中必须包含各维度的长度值),并将其引用值压入栈顶

198

0xc6

ifnull

为nu11时跳转

199

0xc7

ifnonnull

不为nu11时跳转

200

0xc8

goto_w

无条件跳转(宽索引)

201

0xc9

jsr_w

跳转至指定 32 位 offset 位置,并将 jsr_w 下一条指令地址压入栈顶

保留指令

202

Оxca

breakpoint

调试时的断点标记

254

Oxfe

impdep1

为特定软件面预留的语言后门

255

0xff

impdep2

为特定硬件面预留的语言后门

总结:

遇到类似的面试题,不要着急,慢慢分析即可,如果是笔试的话建议慢慢写出来编译的过程,无非也就是做appent操作的时候需要单独创建StringBuffer单独加一个对象,不会很复杂。

祝大家面试都能顺顺利利的。

相关文章
|
3天前
|
XML 缓存 Java
Java大厂面试题
Java大厂面试题
13 0
|
3天前
|
存储 安全 Java
Java大厂面试题
Java大厂面试题
9 0
|
3天前
|
存储 安全 Java
Java大厂面试题
Java大厂面试题
12 0
|
4天前
|
安全 Java
就只说 3 个 Java 面试题 —— 02
就只说 3 个 Java 面试题 —— 02
16 0
|
4天前
|
存储 安全 Java
就只说 3 个 Java 面试题
就只说 3 个 Java 面试题
10 0
|
13天前
|
Java
Java 字符串分割split空字符串丢失解决方案
Java 字符串分割split空字符串丢失解决方案
|
14天前
|
Java 关系型数据库 MySQL
大厂面试题详解:Java抽象类与接口的概念及区别
字节跳动大厂面试题详解:Java抽象类与接口的概念及区别
36 0
|
15天前
|
Java
Java练习题-键盘录入字符串实现大小写转换
Java练习题-键盘录入字符串实现大小写转换
20 2
|
16天前
|
存储 安全 Java
Java中实现高效的字符串拼接技术
【4月更文挑战第6天】在Java编程中,字符串拼接是一个常见的操作。然而,由于字符串的不可变性,频繁的拼接操作可能会导致性能问题。本文将探讨Java中实现高效字符串拼接的技术,包括使用StringBuilder类、StringBuffer类以及Java 8中的StringJoiner类。通过对比这些技术的优缺点,我们将为您提供在不同场景下选择合适的字符串拼接方法的建议。
|
23天前
|
存储 缓存 算法
Java入门高频考查基础知识4(字节跳动面试题18题2.5万字参考答案)
最重要的是保持自信和冷静。提前准备,并对自己的知识和经验有自信,这样您就能在面试中展现出最佳的表现。祝您面试顺利!Java 是一种广泛使用的面向对象编程语言,在软件开发领域有着重要的地位。Java 提供了丰富的库和强大的特性,适用于多种应用场景,包括企业应用、移动应用、嵌入式系统等。下是几个面试技巧:复习核心概念、熟悉常见问题、编码实践、项目经验准备、注意优缺点、积极参与互动、准备好问题问对方和知其所以然等,多准备最好轻松能举一反三。
48 0
Java入门高频考查基础知识4(字节跳动面试题18题2.5万字参考答案)