我们都知道,java中对类型的检查是很严格的,所以我们平操作时,也往往很小心。

  如题: (T[]) new Object[size],这种写法是一般我们是不会干的!但是有点经验的同学,还是会遇到这样写的。那么,今天咱们就来看看,像这样的写法对不对,也顺便深入理解java的类型转换机制吧!


问题1: 如题 (T[]) new Object[size]  的写法对不对?

  答案是肯定的,没毛病。

  为啥呢? 因为 java 的泛型只是语法糖,在java编译后,就不见了,到最后都会转为 object 类型的中间类型,所以,没毛病!


问题2: 如题所示的变量,能直接使用吗?

  答案待定。不过,我们写的代码应该是不会有什么问题了!如下:

MyObjClz[] clzArr = getT();    // 直接获取变量,编译不报错

  然后,由于看起来没毛病,我们就可以坑哧坑哧写后续代码了!

  然而事实证明,这是错的!为啥呢? 你应该知道了,这里有类型转换错误!

  好吧,从这里我们得到一个教训,正向没问题的东西,不代表反向也没问题!

  既然整个数组获取回来,会发生类型转换错误,那么我们可以想办法避开这个问题,比如我一个元素一个元素的获取,应该就没问题了吧。因为我们明确知道内部元素的具体类型,而我们只是做了一个 object 的中间转换而已,所以理论正确。比如:

MyObjClz clz1 = getT()[0];    // 我只获取第一个就行了,因为 整个数组转换已经不OK

  嗯,IDE还是不会报错的,我们又可以坑哧坑哧写代码了。

  糟糕,运行还是异常了!哎,既然都会导致报错,那为嘛要搞这种语法呢?让我们继续看!


问题3:我们到底怎样才可以使用如题创建的变量?

  其实和我们上面最后一个解题思路是一致的,整个数组类型转换是不可能了,那就单个转呗!不过,这个单个是要从源头开始。即示例如下:

MyObjClz clz1 = getTOne(i);    // 直接让方法返回 单个元素

  如上,运行妥妥的,我们终于可以安心睡觉了。但是为啥呢?让我们继续!


问题4:如题所示的语法到底有啥用?

  额,还是很有用的!比如: ArrayList<E>, ArrayQueue<T>, 等等,里面所支持的泛型,最终都会使用到Object 来进行变量保存的,因为既然是泛型,也就是说,在写代码的时候,是不会知道变量类型的,不知道类型自然是保存不了变量的。所以必须使用 Object[] !

下面来看个应用的例子(可以想像为一个栈队列):

 public class ObjectCastToAnother {
public static void main(String[] args) { ArrayAGeneric<User> arrayAGeneric = new ArrayAGeneric<>();
arrayAGeneric.push(new User());
arrayAGeneric.push(new User());
// 正确的使用姿势,返回一个元素,直接使用
User us1 = arrayAGeneric.pop();
System.out.println("us1: " + us1);
// 如下是反而教材,这句是会报错的
User us2 = arrayAGeneric.getQueue()[0];
System.out.println("us2: " + us2);
}
} class ArrayAGeneric<T> {
private T[] queue;
private int tail = 0;
public ArrayAGeneric() {
System.out.println("gen ok");
queue = newArray(10);
} private T[] newArray(int size) {
System.out.println("new array T[]");
return (T[]) new Object[size];
} public void push(T u) {
queue[tail++] = u;
} public T pop() {
return queue[--tail];
} public T[] getQueue() {
return queue;
}
}

  例子一看就懂,就是一个简单的 插入元素,获取元素,使用而已。但是我们的目的是来分析,为什么两种简单的使用,一个会报错,而另一个不会报错,以及 (T[]) new Object[x]为啥不会报错!即如下:

        User us = arrayAGeneric.pop();                // 正确
User us2 = arrayAGeneric.getQueue()[0]; // 错误
return (T[]) new Object[size]; // 什么操作?

  看起来差距只在是由谁来取元素的问题了!那么,到底是不是这样呢?(java理论书上肯定有确切的答案)

那我们换个思路来看问题,然后java代码看不出差别,那么,我们是不是可以换成另一种方式来查看呢?是的,class字节码文件。

反编译一下,会得到两个文件:

javap -verbose -p ObjectCastToAnnother.class  # 反编译class

1. main 文件

 Classfile /D:/www/java/target/classes/com/xxx/tester/ObjectCastToAnnother.class
Last modified 2018-11-18; size 1398 bytes
MD5 checksum 8a1815ea41426d67e1a4b68bed4ca914
Compiled from "ObjectCastToAnnother.java"
public class com.xxx.tester.ObjectCastToAnnother
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #20.#41 // java/lang/Object."<init>":()V
#2 = Class #42 // com/xxx/tester/ArrayAGeneric
#3 = Methodref #2.#41 // com/xxx/tester/ArrayAGeneric."<init>":()V
#4 = Class #43 // com/xxx/pojo/user/User
#5 = Methodref #4.#41 // com/xxx/pojo/user/User."<init>":()V
#6 = Methodref #2.#44 // com/xxx/tester/ArrayAGeneric.push:(Ljava/lang/Object;)V
#7 = Methodref #2.#45 // com/xxx/tester/ArrayAGeneric.pop:()Ljava/lang/Object;
#8 = Fieldref #46.#47 // java/lang/System.out:Ljava/io/PrintStream;
#9 = Class #48 // java/lang/StringBuilder
#10 = Methodref #9.#41 // java/lang/StringBuilder."<init>":()V
#11 = String #49 // us1:
#12 = Methodref #9.#50 // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
#13 = Methodref #9.#51 // java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
#14 = Methodref #9.#52 // java/lang/StringBuilder.toString:()Ljava/lang/String;
#15 = Methodref #53.#54 // java/io/PrintStream.println:(Ljava/lang/String;)V
#16 = Methodref #2.#55 // com/xxx/tester/ArrayAGeneric.getQueue:()[Ljava/lang/Object;
#17 = Class #56 // "[Lcom/xxx/pojo/user/User;"
#18 = String #57 // us2:
#19 = Class #58 // com/xxx/tester/ObjectCastToAnnother
#20 = Class #59 // java/lang/Object
#21 = Utf8 <init>
#22 = Utf8 ()V
#23 = Utf8 Code
#24 = Utf8 LineNumberTable
#25 = Utf8 LocalVariableTable
#26 = Utf8 this
#27 = Utf8 Lcom/xxx/tester/ObjectCastToAnnother;
#28 = Utf8 main
#29 = Utf8 ([Ljava/lang/String;)V
#30 = Utf8 args
#31 = Utf8 [Ljava/lang/String;
#32 = Utf8 arrayAGeneric
#33 = Utf8 Lcom/xxx/tester/ArrayAGeneric;
#34 = Utf8 us
#35 = Utf8 Lcom/xxx/pojo/user/User;
#36 = Utf8 us2
#37 = Utf8 LocalVariableTypeTable
#38 = Utf8 Lcom/xxx/tester/ArrayAGeneric<Lcom/xxx/pojo/user/User;>;
#39 = Utf8 SourceFile
#40 = Utf8 ObjectCastToAnnother.java
#41 = NameAndType #21:#22 // "<init>":()V
#42 = Utf8 com/xxx/tester/ArrayAGeneric
#43 = Utf8 com/xxx/pojo/user/User
#44 = NameAndType #60:#61 // push:(Ljava/lang/Object;)V
#45 = NameAndType #62:#63 // pop:()Ljava/lang/Object;
#46 = Class #64 // java/lang/System
#47 = NameAndType #65:#66 // out:Ljava/io/PrintStream;
#48 = Utf8 java/lang/StringBuilder
#49 = Utf8 us1:
#50 = NameAndType #67:#68 // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
#51 = NameAndType #67:#69 // append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
#52 = NameAndType #70:#71 // toString:()Ljava/lang/String;
#53 = Class #72 // java/io/PrintStream
#54 = NameAndType #73:#74 // println:(Ljava/lang/String;)V
#55 = NameAndType #75:#76 // getQueue:()[Ljava/lang/Object;
#56 = Utf8 [Lcom/xxx/pojo/user/User;
#57 = Utf8 us2:
#58 = Utf8 com/xxx/tester/ObjectCastToAnnother
#59 = Utf8 java/lang/Object
#60 = Utf8 push
#61 = Utf8 (Ljava/lang/Object;)V
#62 = Utf8 pop
#63 = Utf8 ()Ljava/lang/Object;
#64 = Utf8 java/lang/System
#65 = Utf8 out
#66 = Utf8 Ljava/io/PrintStream;
#67 = Utf8 append
#68 = Utf8 (Ljava/lang/String;)Ljava/lang/StringBuilder;
#69 = Utf8 (Ljava/lang/Object;)Ljava/lang/StringBuilder;
#70 = Utf8 toString
#71 = Utf8 ()Ljava/lang/String;
#72 = Utf8 java/io/PrintStream
#73 = Utf8 println
#74 = Utf8 (Ljava/lang/String;)V
#75 = Utf8 getQueue
#76 = Utf8 ()[Ljava/lang/Object;
{
public com.xxx.tester.ObjectCastToAnnother();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 8: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/xxx/tester/ObjectCastToAnnother; public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=4, args_size=1
0: new #2 // class com/xxx/tester/ArrayAGeneric
3: dup
4: invokespecial #3 // Method com/xxx/tester/ArrayAGeneric."<init>":()V
7: astore_1
8: aload_1
9: new #4 // class com/xxx/pojo/user/User
12: dup
13: invokespecial #5 // Method com/xxx/pojo/user/User."<init>":()V
16: invokevirtual #6 // Method com/xxx/tester/ArrayAGeneric.push:(Ljava/lang/Object;)V
19: aload_1
20: new #4 // class com/xxx/pojo/user/User
23: dup
24: invokespecial #5 // Method com/xxx/pojo/user/User."<init>":()V
27: invokevirtual #6 // Method com/xxx/tester/ArrayAGeneric.push:(Ljava/lang/Object;)V
30: aload_1
31: invokevirtual #7 // Method com/xxx/tester/ArrayAGeneric.pop:()Ljava/lang/Object;
34: checkcast #4 // class com/xxx/pojo/user/User
37: astore_2
38: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
41: new #9 // class java/lang/StringBuilder
44: dup
45: invokespecial #10 // Method java/lang/StringBuilder."<init>":()V
48: ldc #11 // String us1:
50: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
53: aload_2
54: invokevirtual #13 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
57: invokevirtual #14 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
60: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
63: aload_1
64: invokevirtual #16 // Method com/xxx/tester/ArrayAGeneric.getQueue:()[Ljava/lang/Object;
67: checkcast #17 // class "[Lcom/xxx/pojo/user/User;"
70: iconst_0
71: aaload
72: astore_3
73: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
76: new #9 // class java/lang/StringBuilder
79: dup
80: invokespecial #10 // Method java/lang/StringBuilder."<init>":()V
83: ldc #18 // String us2:
85: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
88: aload_3
89: invokevirtual #13 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
92: invokevirtual #14 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
95: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
98: return
LineNumberTable:
line 11: 0
line 12: 8
line 13: 19
line 14: 30
line 15: 38
line 16: 63
line 17: 73
line 18: 98
LocalVariableTable:
Start Length Slot Name Signature
0 99 0 args [Ljava/lang/String;
8 91 1 arrayAGeneric Lcom/xxx/tester/ArrayAGeneric;
38 61 2 us Lcom/xxx/pojo/user/User;
73 26 3 us2 Lcom/xxx/pojo/user/User;
LocalVariableTypeTable:
Start Length Slot Name Signature
8 91 1 arrayAGeneric Lcom/xxx/tester/ArrayAGeneric<Lcom/xxx/pojo/user/User;>;
}
SourceFile: "ObjectCastToAnnother.java"

2. ArrayAGeneric 文件

 Classfile /D:/www/java/target/classes/com/xxx/tester/ArrayAGeneric.class
Last modified 2018-11-18; size 1390 bytes
MD5 checksum fc9f7f9311bf542d9f1b03e39e32aba8
Compiled from "ObjectCastToAnnother.java"
class com.xxx.tester.ArrayAGeneric<T extends java.lang.Object> extends java.lang.Object
minor version: 0
major version: 52
flags: ACC_SUPER
Constant pool:
#1 = Methodref #9.#46 // java/lang/Object."<init>":()V
#2 = Fieldref #11.#47 // com/xxx/tester/ArrayAGeneric.tail:I
#3 = Fieldref #48.#49 // java/lang/System.out:Ljava/io/PrintStream;
#4 = String #50 // gen ok
#5 = Methodref #51.#52 // java/io/PrintStream.println:(Ljava/lang/String;)V
#6 = Methodref #11.#53 // com/xxx/tester/ArrayAGeneric.newArray:(I)[Ljava/lang/Object;
#7 = Fieldref #11.#54 // com/xxx/tester/ArrayAGeneric.queue:[Ljava/lang/Object;
#8 = String #55 // new array T[]
#9 = Class #56 // java/lang/Object
#10 = Class #13 // "[Ljava/lang/Object;"
#11 = Class #57 // com/xxx/tester/ArrayAGeneric
#12 = Utf8 queue
#13 = Utf8 [Ljava/lang/Object;
#14 = Utf8 Signature
#15 = Utf8 [TT;
#16 = Utf8 tail
#17 = Utf8 I
#18 = Utf8 <init>
#19 = Utf8 ()V
#20 = Utf8 Code
#21 = Utf8 LineNumberTable
#22 = Utf8 LocalVariableTable
#23 = Utf8 this
#24 = Utf8 Lcom/xxx/tester/ArrayAGeneric;
#25 = Utf8 LocalVariableTypeTable
#26 = Utf8 Lcom/xxx/tester/ArrayAGeneric<TT;>;
#27 = Utf8 newArray
#28 = Utf8 (I)[Ljava/lang/Object;
#29 = Utf8 size
#30 = Utf8 (I)[TT;
#31 = Utf8 push
#32 = Utf8 (Ljava/lang/Object;)V
#33 = Utf8 u
#34 = Utf8 Ljava/lang/Object;
#35 = Utf8 TT;
#36 = Utf8 (TT;)V
#37 = Utf8 pop
#38 = Utf8 ()Ljava/lang/Object;
#39 = Utf8 ()TT;
#40 = Utf8 getQueue
#41 = Utf8 ()[Ljava/lang/Object;
#42 = Utf8 ()[TT;
#43 = Utf8 <T:Ljava/lang/Object;>Ljava/lang/Object;
#44 = Utf8 SourceFile
#45 = Utf8 ObjectCastToAnnother.java
#46 = NameAndType #18:#19 // "<init>":()V
#47 = NameAndType #16:#17 // tail:I
#48 = Class #58 // java/lang/System
#49 = NameAndType #59:#60 // out:Ljava/io/PrintStream;
#50 = Utf8 gen ok
#51 = Class #61 // java/io/PrintStream
#52 = NameAndType #62:#63 // println:(Ljava/lang/String;)V
#53 = NameAndType #27:#28 // newArray:(I)[Ljava/lang/Object;
#54 = NameAndType #12:#13 // queue:[Ljava/lang/Object;
#55 = Utf8 new array T[]
#56 = Utf8 java/lang/Object
#57 = Utf8 com/xxx/tester/ArrayAGeneric
#58 = Utf8 java/lang/System
#59 = Utf8 out
#60 = Utf8 Ljava/io/PrintStream;
#61 = Utf8 java/io/PrintStream
#62 = Utf8 println
#63 = Utf8 (Ljava/lang/String;)V
{
private T[] queue;
descriptor: [Ljava/lang/Object;
flags: ACC_PRIVATE
Signature: #15 // [TT; private int tail;
descriptor: I
flags: ACC_PRIVATE public com.xxx.tester.ArrayAGeneric();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=3, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: iconst_0
6: putfield #2 // Field tail:I
9: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
12: ldc #4 // String gen ok
14: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
17: aload_0
18: aload_0
19: bipush 10
21: invokespecial #6 // Method newArray:(I)[Ljava/lang/Object;
24: putfield #7 // Field queue:[Ljava/lang/Object;
27: return
LineNumberTable:
line 24: 0
line 23: 4
line 25: 9
line 26: 17
line 27: 27
LocalVariableTable:
Start Length Slot Name Signature
0 28 0 this Lcom/xxx/tester/ArrayAGeneric;
LocalVariableTypeTable:
Start Length Slot Name Signature
0 28 0 this Lcom/xxx/tester/ArrayAGeneric<TT;>; private T[] newArray(int);
descriptor: (I)[Ljava/lang/Object;
flags: ACC_PRIVATE
Code:
stack=2, locals=2, args_size=2
0: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #8 // String new array T[]
5: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: iload_1
9: anewarray #9 // class java/lang/Object
12: checkcast #10 // class "[Ljava/lang/Object;"
15: areturn
LineNumberTable:
line 30: 0
line 31: 8
LocalVariableTable:
Start Length Slot Name Signature
0 16 0 this Lcom/xxx/tester/ArrayAGeneric;
0 16 1 size I
LocalVariableTypeTable:
Start Length Slot Name Signature
0 16 0 this Lcom/xxx/tester/ArrayAGeneric<TT;>;
Signature: #30 // (I)[TT; public void push(T);
descriptor: (Ljava/lang/Object;)V
flags: ACC_PUBLIC
Code:
stack=5, locals=2, args_size=2
0: aload_0
1: getfield #7 // Field queue:[Ljava/lang/Object;
4: aload_0
5: dup
6: getfield #2 // Field tail:I
9: dup_x1
10: iconst_1
11: iadd
12: putfield #2 // Field tail:I
15: aload_1
16: aastore
17: return
LineNumberTable:
line 35: 0
line 36: 17
LocalVariableTable:
Start Length Slot Name Signature
0 18 0 this Lcom/xxx/tester/ArrayAGeneric;
0 18 1 u Ljava/lang/Object;
LocalVariableTypeTable:
Start Length Slot Name Signature
0 18 0 this Lcom/xxx/tester/ArrayAGeneric<TT;>;
0 18 1 u TT;
Signature: #36 // (TT;)V public T pop();
descriptor: ()Ljava/lang/Object;
flags: ACC_PUBLIC
Code:
stack=4, locals=1, args_size=1
0: aload_0
1: getfield #7 // Field queue:[Ljava/lang/Object;
4: aload_0
5: dup
6: getfield #2 // Field tail:I
9: iconst_1
10: isub
11: dup_x1
12: putfield #2 // Field tail:I
15: aaload
16: areturn
LineNumberTable:
line 39: 0
LocalVariableTable:
Start Length Slot Name Signature
0 17 0 this Lcom/xxx/tester/ArrayAGeneric;
LocalVariableTypeTable:
Start Length Slot Name Signature
0 17 0 this Lcom/xxx/tester/ArrayAGeneric<TT;>;
Signature: #39 // ()TT; public T[] getQueue();
descriptor: ()[Ljava/lang/Object;
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: getfield #7 // Field queue:[Ljava/lang/Object;
4: areturn
LineNumberTable:
line 43: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/xxx/tester/ArrayAGeneric;
LocalVariableTypeTable:
Start Length Slot Name Signature
0 5 0 this Lcom/xxx/tester/ArrayAGeneric<TT;>;
Signature: #42 // ()[TT;
}
Signature: #43 // <T:Ljava/lang/Object;>Ljava/lang/Object;
SourceFile: "ObjectCastToAnnother.java"

其实从 main 文件中已经看出端倪,第120~123行,即 us1 赋值的地方:

        30: aload_1
31: invokevirtual #7 // Method com/xxx/tester/ArrayAGeneric.pop:()Ljava/lang/Object;
34: checkcast #4 // class com/xxx/pojo/user/User
37: astore_2

这里看到,有一个 checkcast 的指令,即是进行类型转换检查,而本身的 pop() 后的元素类型一致,因此运行OK!

我们来看下一取值方式,第134~138行,即 us2 赋值的地方:

        63: aload_1
64: invokevirtual #16 // Method com/xxx/tester/ArrayAGeneric.getQueue:()[Ljava/lang/Object;
67: checkcast #17 // class "[Lcom/xxx/pojo/user/User;"
70: iconst_0
71: aaload

  看到了吧,关键的地方: checkcast class "[Lcom/xxx/pojo/user/User", 即将获取到的值进行 数组类型的转换检查,如此检查,自然是通不过的了。所以,理解了吧,是因为,数组元素的获取顺序为先进行类型转换,然后再获取元素值!

  现在,还剩下一个问题: 为什么通过 getOne() 的形式,代码就是可行的呢?

  这个问题的答案,在 ArrayAGeneric 的文件中,可以轻松找到答案:

ArrayAGeneric 文件,第 174~184行:

         0: aload_0
1: getfield #7 // Field queue:[Ljava/lang/Object;
4: aload_0
5: dup
6: getfield #2 // Field tail:I
9: iconst_1
10: isub
11: dup_x1
12: putfield #2 // Field tail:I
15: aaload
16: areturn

  可以看出来,这里就只是一个数组元素的获取过程,返回类型为 Object, 而此 Object 的原始类型即是泛型指定的。因此,在外部进行转换自然也不会错!

好了,到此,疑问已经得到回答。是类型转换的检查时机导致了我们的代码错误。

另外,我们还可以继续看一下  newArray() 的代码:

         0: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #8 // String new array T[]
5: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: iload_1
9: anewarray #9 // class java/lang/Object
12: checkcast #10 // class "[Ljava/lang/Object;"
15: areturn

  这里也可以明显的看出, T[] 其实就是 Object[] 。

数组类型的强转要特别注意,其向上转型是ok的,向下转型则是不被允许的,因为继承的关系,父类不能保证所有的所有的元素都能强制转换(元素可以是指定类型的任意子类),所以干脆杜绝了所有的向下转型了!(我猜应该是出于性能的考虑)

  不要以为ArrayList<T>中的T是指的具体泛型类,完。

从字节码看java类型转换【 深入理解 (T[]) new Object[size] 】的更多相关文章

  1. 从字节码看java中 this 的隐式传参

    从字节码看java中 this 隐式传参具体体现(和python中的self如出一辙,但是比python中藏得更深),也发现了 static 与 非 static 方法的区别所在! static与非s ...

  2. 通过字节码分析Java方法的静态分派与动态分派机制

    在上一次[https://www.cnblogs.com/webor2006/p/9723289.html]中已经对Java方法的静态分派在字节码中的表现了,也就是方法重载其实是一种静态分派的体现,这 ...

  3. 通过字节码分析Java异常处理机制

    在上一次[https://www.cnblogs.com/webor2006/p/9691523.html]初步对异常表相关的概念进行了了解,先来回顾一下: 其源代码也贴一下: 下面来看一下jclas ...

  4. 根据字节码探讨java自增运算符的原理

    public class Test { static int x, y; public static void main(String args[]) { x++; myMethod(); Syste ...

  5. 通过字节码分析java中的switch语句

    在一次做题中遇到了switch的问题,由于对switch执行顺序的不了解,在这里简单的通过字节码的方式理解一下switch执行顺序(题目如下): public class Ag{ static pub ...

  6. 透过字节码分析java基本类型数组的内存分配方式。

    我们知道java中new方式创建的对象都是在堆中创建的,而局部变量对应的值存放在栈上.那么java中的int [] arr={1,2,3}是存放在什么地方的呢,int []arr = new int[ ...

  7. 从源码看Java集合之ArrayList

    Java集合之ArrayList - 吃透增删查改 从源码看初始化以及增删查改,学习ArrayList. 先来看下ArrayList定义的几个属性: private static final int ...

  8. 从源码看java中Integer的缓存问题

    在开始详细的说明问题之前,我们先看一段代码 public static void compare1(){ Integer i1 = 127, i2 = 127, i3 = 128, i4 = 128; ...

  9. 从源码看java线程状态

    关于java线程状态,网上查资料很混乱,有的说5种状态,有的说6种状态,初学者搞不清楚这个线程状态到底是怎么样的,今天我讲一下如何看源码去解决这个疑惑. 直接上代码: public class Thr ...

随机推荐

  1. JS獲取URL的參數

    function GetQueryString(name) { var reg = new RegExp("(^|&)"+ name +"=([^&]*) ...

  2. 使用Mobile Device Manager Plus mdm软件进行完备的移动设备管理

    使用Mobile Device Manager Plus mdm软件进行完备的移动设备管理 什么是移动设备管理(mdm管理系统)? 移动设备管理(mdm管理系统)旨在管理企业内移动设备.管理员使用md ...

  3. python语法之正则

    1.正则表达式是用来干嘛的? 用来匹配字符串的  ,其中正则是意思是模糊匹配. 就其本质而言,正则表达式(或 RE)是一种小型的.高度专业化的编程语言,(在Python中)它内嵌在Python中,并通 ...

  4. 每日一练ACM 2019.0422

    Problem Description 根据输入的半径值,计算球的体积.   Input 输入数据有多组,每组占一行,每行包括一个实数,表示球的半径.   Output 输出对应的球的体积,对于每组输 ...

  5. .gvfs: Permission denied

    命令行输入umount .gvfs rm -rf .gvfs

  6. Java性能优化的50个细节(珍藏版)

    原文地址:https://www.toutiao.com/i6595499804082569742/ 在JAVA程序中,性能问题的大部分原因并不在于JAVA语言,而是程序本身.养成良好的编码习惯非常重 ...

  7. Unity编辑器扩展-Custom List, displaying data your way

    本文转自http://catlikecoding.com/unity/tutorials/editor/custom-list/ Custom List, displaying data your w ...

  8. java开发师笔试面试每日12题(1)

    1.什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”?Java虚拟机是一个可以执行Java字节码的虚拟机进程.Java源文件被编译成能被Java虚拟机执行的字节码文件.Java被设计 ...

  9. 修改mysql登录密码

    通过cmd   登录进mysql系统后,输入 : set password for root@localhost = password('admin'); 其中admin  为新密码: 导入外部数据库 ...

  10. DNS: Internet’s Directory

    关于DNS 互联网上几乎一切活动都以DNS请求开始.DNS(Domain Name System)是Internet的目录.访问URL时,设备所要做的第一件事就是询问目录,根据域名查出IP地址. 查询 ...