Java基础-1 基础数据类型及常用引用数据类型

Java基础-1 数据类型及常用引用数据类型

基本数据类型
  1. java四类八种基本数据类型:
基本数据类型占用字节默认值包装类表数范围
byte字节型10Byte-128~127
short(短整型)20Short-215~215-1
int(整型)40Integer-231~231-1
long(长整型)80.0Long-263~263-1
float(浮点型)40.0fFloat-3.403E38~3.403E38
double(双精度)80.0Double-1.798E308~1.798E308
char(字符型)2/u000(空格)Character
boolean(布尔型)系统没有提供size方法falseBoolean
  • 在栈中可以直接分配内存的数据是基本数据类型。
  • 引用数据类型:是数据的引用在栈中,但是他的对象在堆中。
  1. 注意问题
  • 初始默认值不同。int的默认值为0,而Integer的默认值为null,即Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况,例如,要想表达出没有参加考试和考试成绩为0的区别,则只能使用Integer。
String
  • String类主要由char数组、偏移量、和String长度组成。
  • char数组表示String的内容,但真实的内容还需要由偏移量和长度在char数组中定位和截取。

基本特点:

  1. 不变性:String对象一旦生成,则不能对它进行改变。

  2. 针对常量池的优化,String对象值相同时,引用常量池中的同一个

  3. 类的final定义,不能被继承,String类保存一个字符串在常量池就可以安全共享

  4. 源码解读
    -1.6版本 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); //使用的是和父字符串同一个char数组value
 }
    }
  • 截取后新建字符串的构造方法
String(int offset, int count, char value[]) {
    this.value = value;
    this.offset = offset;
     this.count = count;
}

this.value=value这种实现就出现问题了,因为String类中有几个私有的成员变量:

private final char value[];
private final int offset;
 private final int count;
 private int hash; // Default to 0

原因:如果你有一个很长很长的字符串,但是当你使用substring进行切割的时候你只需要很短的一段。

这可能导致性能问题,因为你需要的只是一小段字符序列,但是你却引用了整个字符串(因为这个非常长的字符数组一直在被引用,所以无法被回收,就可能导致内存泄露)

JDK 7中的subString方法,其使用new String创建了一个新字符串,避免对老字符串的引用。从而解决了内存泄露问题。

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);   //创建了一个新的字符串
    }
    
    public String(char value[], int offset, int count) {
        if (offset < 0) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count <= 0) {
            if (count < 0) {
                throw new StringIndexOutOfBoundsException(count);
            }
            if (offset <= value.length) {
                this.value = "".value;
                return;
            }
        }
        // Note: offset or count might be near -1>>>1.
        if (offset > value.length - count) {
            throw new StringIndexOutOfBoundsException(offset + count);
        }
        this.value = Arrays.copyOfRange(value, offset, offset+count);
    }
    
    public static char[] copyOfRange(char[] original, int from, int to) {
        int newLength = to - from;
        if (newLength < 0)
            throw new IllegalArgumentException(from + " > " + to);
        char[] copy = new char[newLength];  //新建了一个字符数组
        System.arraycopy(original, from, copy, 0,
                         Math.min(original.length - from, newLength));
        return copy;
    }
String常见面试题
  • 基础知识:

1、==:既可以比较基本数据类型,又可以比较引用数据类型。基本数据类型比较的是值,引用数据类型比较的是地址。

equals只能比较引用数据类型,如果没有重写Object类中的equals方法,equals方法和==号比较引用数据类型无区别 ,重写后的equals方法比较的是对象中的属性。

2、字符串常量存储在常量池,而new String 创建对象,在编译期间不能确定具体的值,所以会在 在在内存中创建的一个地址。 所以下面的第三题用等号比较的两个地址不同,但是属性是相同的,所以用equals比较的是属性值,所以相同。

  1. 判断定义为String类型的s1和s2是否相等
  • String s1 = “abc”;

  • String s2 = “abc”;

  • System.out.println(s1 == s2); //true ,比较地址值,都在常量池,相等

  • System.out.println(s1.equals(s2)); //true,equals中,先判断两个对象的地址值,地址值相同,默认就是同一个对象,不会继续equalse中的具体值是否相等的判断了,直接会返回true。

  1. 下面这句话在内存中创建了几个对象?
  • String s1 = new String(“abc”); //两个对象 :abc在常量池,有自己的地址。 new String 创建 对象,在编译期间不能确定具体的值,所以会在 在在内存中创建的一个地址。
  1. 判断定义为String类型的s1和s2是否相等
  • String s1 = new String(“abc”);

  • String s2 = “abc”;

  • System.out.println(s1 == s2); //false

  • System.out.println(s1.equals(s2)); //true

  1. 判断定义为String类型的s1和s2是否相等
  • String s1 = “a” + “b” + “c”;

  • String s2 = “abc”;

  • System.out.println(s1 == s2); //true 地址值相同,都是常量,在常量池里面

  • System.out.println(s1.equals(s2)); //true 地址值相同,默认同一个对象,值当然也是相等的。

  1. 判断定义为String类型的s1和s2是否相等
  • String s1 = “ab”;

  • String s2 = “abc”;

  • String s3 = s1 + “c”;

  • System.out.println(s3 == s2); //false 不相等,s1是变量,编译的时候确定不了值,在内存中会创建值,s3在堆内存中,。s2在常量池,所以不相等。

  • System.out.println(s3.equals(s2)); //true 比较两个对象的值相等。

解释:这就关系到底层的运行图了

  • String s1 = “abc”;

String s2 = “abc”;

s1会在常量池中创建,s2先查看常量池中有没有,如果有的话就指向它,如果没有就在常量池中创建一个然后指向它。所以s1和s2的两种比较是相同的。

  • String s2 = “abc”;

以下几个都是用了String包的构造方法,可能存在内存泄漏的问题

  1. Integer.toString(int)
  2. Long.toString(long)
  3. String.concat(String)
  4. String.replace(char,char)
  5. String.subString(int,int)
  6. String.toLowerCase(Locade)
  7. String.toUpperCase(Locade)
  8. String.valueOf(char)

字符串截取split() 效率更高的 StringTokenizer(String str, String delim )

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值