Vấn đề về Integer và String

Chào mọi người.
Em đang theo học về lập trình java và em gặp một chút vấn đề trong việc xử lý Integer và String mong ace trong nhóm giúp đỡ ạ.
Ví dụ 1:

  Integer a = 127; 
  Integer b = 127;
 boolean check c = a==b;//true
// a và b nhận giá trị từ -128 đến 127 thì c đều trả về true ngoài khoảng đó ra thì c trả về false

Ví dụ 2:

 String a = "ABC";
 String c = "ABCDEF";
 String b = c.subString(0,3);// trả về ABC
 String d = c.subString(0,3):
 String e = c.subString(0,c.length());// trả về ABCDEF
 boolean check c1 = a==b;//false
 boolean check c2 = b==d;//false
 boolean check c3 = e==c;//true

Mọi người có thể giải thích cho em lý do tại sao nó lại trả về kết quả như vậy không ạ.
Cám ơn đã xem ạ.

  1. em có thể check source Java hàm Integer.valueOf() để hiểu rõ hơn vì:

    Integer a = 127; //=Integer.valueOf(127);
    Integer b = 127; //=Integer.valueOf(127);

và hàm ValueOf nó thể này:

public static Integer valueOf(int i) {
    if(i >= -128 && i <= IntegerCache.high)
        return IntegerCache.cache[i + 128];
    else
        return new Integer(i);
}

-> giá trị từ -127 đến 128 được cache lại, mục đích vì những số trong khoảng này dùng tần suất cực nhiều -> nên cache lại đỡ tốn bộ nhớ.

  1. check hàm subString():

    String a = “ABC”; // String from pool
    String c = “ABCDEF”; // String from pool
    String b = c.subString(0,3);// new String
    String d = c.subString(0,3): // new String

hàm subString:

public String substring(int beginIndex, int endIndex) {
    if (beginIndex < 0) {
        throw new StringIndexOutOfBoundsException(beginIndex);
    }
    if (endIndex > count) {
        throw new StringIndexOutOfBoundsException(endIndex);
    }
    if (beginIndex > endIndex) {
        throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
    }
    return ((beginIndex == 0) && (endIndex == count)) ? this :
        new String(offset + beginIndex, endIndex - beginIndex, value);
}

-> new String() luôn tạo ra 1 object mới nên reference luôn khác với những cái khác;

4 Likes

Chỗ này em chưa hiểu lắm, anh Cương có thể giải thích lại đoạn này đc không ạ?

đó là source của Java, mục đích là để lấy subString, a nghĩ hiểu thế là đủu
rồi :slight_smile:

1 Like

là do phiên bản cũ Java 6 thì phải, String có thêm offset để substring ko cần tạo chuỗi mới mà xài ké nội dung của chuỗi cũ luôn

new String(offset + beginIndex, endIndex - beginIndex, value); sẽ xài private constructor này:

  644       // Package private constructor which shares value array for speed.
  645       String(int offset, int count, char value[]) {
  646           this.value = value;
  647           this.offset = offset;
  648           this.count = count;
  649       }
//s gồm
//  value -> [a,b,c,d,e,f]
//  offset = 0
//  count = 6
//  hash = 0  (khi gọi hashCode() thì mới tính 1 lần hash code của "abcdef")
String s = "abcdef";

//a gồm
//  value -> [a,b,c,d,e,f]   (mảng mà s.value trỏ tới)
//  offset = 2
//  count = 2
//  hash = 0 (khi gọi hashCode() thì mới tính 1 lần hash code  của "cd")
String a = s.substring(2, 4); //"cd"

do có offset mà ko cần tạo mảng value mới, xài ké value của s, tiết kiệm bộ nhớ 1 tí. Nhưng sang Java 7u6 ko xài nữa:

    public String substring(int beginIndex, int endIndex) {
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        if (endIndex > value.length) {
            throw new StringIndexOutOfBoundsException(endIndex);
        }
        int subLen = endIndex - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return ((beginIndex == 0) && (endIndex == value.length)) ? this
                : new String(value, beginIndex, subLen);
    }

Chuỗi bây giờ chỉ còn có mảng value và int hash thôi, offset và count ko cần nữa

2 Likes

Cảm ơn a :slight_smile: Em hiểu r.

Dạ em cám ơn.
cái IntegerCache cái lớp đó lạ quá em chưa từng gặp… :slight_smile:
Mà anh ơi mình cần tìm xem các phương thức có sẵn của java được viết như thế nào( hay source Java) thì tìm ở đâu ạ.

Em có thể xem ở đây:
http://grepcode.com/

1 Like

dạ vâng em cám ơn anh :slight_smile:

cho em hỏi luôn vì sao thế này nhỉ

int a = 300;
Integer b = new Integer(300);
Integer c = 300;
c=a;

a==b // true , chỗ này sao a lại bằng b đc nhỉ , b tham chiếu đến 1 vùng nhớ trên heap , a thì lại chứa trực tiếp dữ liệu ??
b==c // false ????

a là kiểu int. Do đó khi thực hiện phép so sánh a với b sẽ là so sánh theo giá trị vì kiểu int là kiểu nguyên thủy, không có tham chiếu để mà so sánh nên b sẽ được unboxed về int sau đó so sánh giá trị. Khi đó a == b; sẽ tương đương với a == b.intValue();
b và c đều là kiểu object do đó phép so sánh == sẽ so sánh theo tham chiếu của b và c trong bộ nhớ.
Phép gán c = a bạn mong đợi c sẽ có địa chỉ giống như a nhưng thực tế java không hoạt động như vậy. Khi đó a sẽ được boxed về kiểu Integer. Khi đó c = a; sẽ tương đương với c = new Integer(a);

4 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?