>  기사  >  Java  >  Java 기본 검토: 기본 데이터 유형 및 문자열 유형

Java 기본 검토: 기본 데이터 유형 및 문자열 유형

php是最好的语言
php是最好的语言원래의
2018-08-02 14:53:272048검색

1. 기본 데이터 유형

Java에는 8가지 기본 데이터 유형, 4가지 정수 유형(byte, short)이 있습니다. , int, long), 소수 유형 2개(float, double), 문자 유형 1개(char), 부울 유형 1개(boolean)

short-2^15 ~ 2^15 - 1int48
byte 값 범위
byte#🎜🎜 ##🎜 🎜#1 -2^7 ~ 2^7 - 1
2 #🎜🎜 #
#🎜 🎜#- 2^31 ~ 2^31 - 1 long
-2^63 ~ 2^ 63 - 1

(1바이트는 8비트 바이너리를 나타냄) float는 32비트, double은 64비트, char는 16비트, boolean은 1비트를 차지합니다.

Java는 Object이기 때문에 -지향# 🎜🎜#은 언어이므로 이러한 8가지 기본 데이터 유형에는 Byte, Short, Integer, Long, Float, Double, Character 및 Boolean과 같은 해당 패키징 클래스가 있습니다. 이러한 8가지 기본 유형과 해당 포장 유형 간의 할당은 자동 박스 포장 및 언박싱을 통해 완료됩니다.

Integer a = 1; // 基本数据类型int自动装箱为Integer包装类(实际上在编译时会调用Integer .valueOf方法来装箱)int b = a;  // 自动拆箱(实际上会在编译调用intValue)

그럼 new Integer(123)Integer.valueOf(123)의 차이점은 무엇인가요?

new Integer(123)Integer.valueOf(123) 有什么区别?

new Integer(123) 每次都会创建一个对象,而 Integer.valueOf(123) 使用到了缓存对象,因此多次使用Integer.valueOf(123) 时,只会取得同一个对象的引用。

Integer a = new Integer(123);Integer b = new Integer(123);
System.out.println(x == y);    // falseInteger c = Integer.valueOf(123);Integer d = Integer.valueOf(123);
System.out.println(z == k);   // true

编译器会在自动装箱过程调用 valueOf() 方法,因此多个 Integer 实例使用自动装箱来创建并且值相同,那么就会引用相同的对象。

Integer m = 123;Integer n = 123;
System.out.println(m == n); // true

根据查看Integer类的源码发现,使用valueOf()时,先判断值是否在缓存池中,如果在的话就直接返回缓存池的内容。

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

但是看下面的代码

    Integer i1 = 128;    Integer i2 = 128;
    System.out.println(i1 == i2); //false

发现返回的是false,这是因为在Integer中,缓存池的范围为: -128 ~ 127

private static class IntegerCache {
        static final int low = -128;        static final int high;        static final Integer cache[];        static {            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");            if (integerCacheHighPropValue != null) {                try {                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];            int j = low;            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }        private IntegerCache() {}
    }

2.String类型

除了上面的八个基本数据类型,String类也是在写程序中最常用的一种类型。

String类被声明为final,所以它不可以被继承。其内部使用 char 数组存储数据,该数组被声明为 final,这意味着 value 数组初始化之后就不能再引用其它数组,并且 String 内部没有改变 value 数组的方法,因此可以保证 String 不可变。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

String.intern()

使用 String.intern() 可以保证相同内容的字符串变量引用相同的内存对象。

下面示例中,s1 和 s2 采用 new String() 的方式新建了两个不同对象,而 s3 是通过 s1.intern() 方法取得一个对象引用,这个方法首先把 s1 引用的对象放到 String Pool(字符串常量池)中,然后返回这个对象引用。因此 s3 和 s1 引用的是同一个字符串常量池的对象。

String s1 = new String("aaa");String s2 = new String("aaa");
System.out.println(s1 == s2);           // falseString s3 = s1.intern();
System.out.println(s1.intern() == s3);  // true

如果是采用 “bbb” 这种使用双引号的形式创建字符串实例,会自动地将新建的对象放入 String Pool 中。

String s4 = "bbb";String s5 = "bbb";
System.out.println(s4 == s5);  // true

在 Java 7 之前,字符串常量池被放在运行时常量池中,它属于永久代。而在 Java 7,字符串常量池被放在堆中。这是因为永久代的空间有限,在大量使用字符串的场景下会导致 OutOfMemoryError 错误。

那么知道String不可变性,那这样设计有什么好处呢?

1.字符串池的需要

字符串常量池(String intern pool) 是Java堆内存中一个特殊的存储区域, 当创建一个String对象时。假如此字符串值已经存在于常量池中,则不会创建一个新的对象,而是引用已经存在的对象。
Java 기본 검토: 기본 데이터 유형 및 문자열 유형

2.允许String对象缓存HashCode

Java中String对象的哈希码被频繁地使用, 比如在hashMap 等容器中。

字符串不变性保证了hash码的唯一性,因此可以放心地进行缓存。这也是一种性能优化手段,意味着不必每次都去计算新的哈希码

3.安全性

String被许多的Java类(库)用来当做参数,例如 网络连接地址URL,文件路径path,还有反射机制所需要的String参数等,假若String不是固定不变的,将会引起各种安全隐患。

boolean connect(string s){  
    if (!isSecure(s)) {   
throw new SecurityException();   
}  
    // 如果在其他地方可以修改String,那么此处就会引起各种预料不到的问题/错误   
    causeProblem(s);  
}

4.线程安全

String 不可变性天生具备线程安全,可以在多个线程中安全地使用。

这篇文章有详细的介绍。

String是不可变,那么有没有可变的字符串呢?

在Java中提供了StringBufferStringBuilder,是可变的。在String中,定义的是一个final字符数组,所以不可变,而StringBuffer和StringBuilder因为继承了AbstractStringBuilder,根据源码可看出是一个可变的字符数组。

public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence{
     AbstractStringBuilder(int capacity) {
            value = new char[capacity];
        }    /**
     * The value is used for character storage.
     */
    char[] value;

根据源码还可以知道,StringBuffer是线程安全的,其中的方法都被synchronizednew Integer(123)는 매번 객체를 생성하는데, Integer.valueOf(123)는 캐시 객체를 사용하므로 사용됩니다. 여러 번 Integer.valueOf(123)는 동일한 객체에 대한 참조만 가져옵니다.

rrreee

컴파일러는 오토박싱 프로세스 중에 valueOf() 메서드를 호출하므로 오토박싱을 사용하여 여러 Integer 인스턴스가 생성되고 동일한 값을 가지며 동일한 값을 참조합니다. 물체.

rrreee

Integer 클래스의 소스코드에 따르면 valueOf()를 사용할 때 해당 값이 캐시 풀에 있는지 먼저 확인하고, 그렇다면 , 캐시 풀의 내용을 직접 반환합니다. rrreee아래 코드를 보면

rrreee

false가 반환되는 것을 알 수 있습니다. 이는 Integer에서 캐시 풀 범위가 -128 ~ 127#🎜🎜이기 때문입니다. # rrreee

2.String 유형

위의 8가지 기본 데이터 유형 외에도 String 클래스는 프로그램 작성에 가장 일반적으로 사용되는 유형이기도 합니다. String 클래스는 final로 선언되어 상속될 수 없습니다. 내부적으로 char 배열을 사용하여 데이터를 저장하고 배열을 final로 선언하는데, 이는 값 배열이 초기화된 후에는 다른 배열을 참조할 수 없으며, 값 배열을 변경할 수 있는 String의 내부 메서드가 없으므로 String 불변성을 보장할 수 있습니다.

rrreee

String.intern()#🎜🎜##🎜🎜##🎜🎜#String.intern()을 사용하면 동일한 내용을 가진 문자열 변수가 동일한 메모리를 참조하도록 할 수 있습니다. 물체. #🎜🎜##🎜🎜#다음 예에서 s1과 s2는 new String()을 사용하여 두 개의 새 객체를 생성하고 s3은 s1.intern() 메서드를 통해 객체 참조를 얻습니다. 이 메서드는 먼저 s1을 참조합니다. String Pool(문자열 상수 풀)에 배치된 다음 객체 참조가 반환됩니다. 따라서 s3과 s1은 동일한 문자열 상수 풀 개체를 참조합니다. #🎜🎜#rrreee#🎜🎜#"bbb"를 사용하여 큰따옴표를 사용하여 문자열 인스턴스를 생성하면 새로 생성된 객체가 자동으로 String Pool에 저장됩니다. #🎜🎜#rrreee#🎜🎜#Java 7 이전에는 문자열 상수 풀이 영구 세대에 속한 런타임 상수 풀에 배치되었습니다. Java 7에서는 문자열 상수 풀이 힙에 배치됩니다. 영구 생성에는 공간이 제한되어 문자열이 광범위하게 사용되는 시나리오에서 OutOfMemoryError 오류가 발생할 수 있기 때문입니다. #🎜🎜##🎜🎜#String이 불변이라는 것을 알면 이 디자인의 이점은 무엇입니까? #🎜🎜##🎜🎜##🎜🎜#1. 문자열 풀의 필요성#🎜🎜##🎜🎜##🎜🎜#문자열 인턴 풀은 문자열을 생성할 때 Java 힙 메모리의 특수 저장 영역입니다. 물체. 이 문자열 값이 상수 풀에 이미 존재하는 경우 새 개체가 생성되지 않지만 기존 개체가 참조됩니다. #🎜🎜#여기에 사진 설명을 쓰세요# 🎜🎜##🎜🎜##🎜🎜#2. String 객체가 HashCode를 캐시하도록 허용#🎜🎜##🎜🎜##🎜🎜#Java에서 String 객체의 해시 코드는 hashMap과 같은 컨테이너에서 자주 사용됩니다. . #🎜🎜##🎜🎜#String 불변성은 해시 코드의 고유성을 보장하므로 안심하고 캐시할 수 있습니다. 이는 성능 최적화이기도 합니다. 즉, 매번 새로운 해시 코드를 계산할 필요가 없습니다 #🎜🎜##🎜🎜##🎜🎜#3 보안 많은 Java 클래스(라이브러리)에서 매개변수로 사용됩니다. 반사 메커니즘에 필요한 네트워크 연결 주소 URL, 파일 경로 경로 및 문자열 매개 변수로 문자열이 수정되지 않으면 다양한 보안 위험이 발생합니다. #🎜🎜#rrreee#🎜🎜##🎜🎜#4. 스레드 안전성 #🎜🎜##🎜🎜##🎜🎜#String 불변성은 본질적으로 스레드로부터 안전하며 여러 스레드에서 안전하게 사용할 수 있습니다. #🎜🎜##🎜🎜#이 글에는 자세한 소개가 있습니다. #🎜🎜##🎜🎜#String은 불변인데, 가변 문자열이 있나요? #🎜🎜##🎜🎜#은 Java에서 변수인 #🎜🎜#StringBuffer#🎜🎜# 및 #🎜🎜#StringBuilder#🎜🎜#을 제공합니다. String에는 최종 문자 배열이 정의되어 있으므로 변경할 수 없습니다. 그러나 StringBuffer와 StringBuilder는 #🎜🎜#AbstractStringBuilder#🎜🎜#을 상속하므로 소스 코드에서 가변 문자 배열임을 알 수 있습니다. #🎜🎜#rrreeerrreee#🎜🎜# 소스 코드에 따르면 StringBuffer는 스레드로부터 안전하며 해당 메서드는 모두 동기화에 의해 수정된다는 것도 알 수 있습니다. #🎜🎜##🎜🎜#관련 기사: #🎜🎜##🎜🎜##🎜🎜#JavaScript 기본 데이터 유형_기본 지식#🎜🎜##🎜🎜##🎜🎜##🎜🎜# 및 스트림#🎜🎜##🎜🎜##🎜🎜#관련 동영상: #🎜🎜##🎜🎜#

데이터 유형의 개요 및 분류 - JAVA 초보자용 비디오 튜토리얼

위 내용은 Java 기본 검토: 기본 데이터 유형 및 문자열 유형의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.