String难点
- hashCode方法
- toString方法
- String的不可变特性
多看注释哦
MyString
package mystring;
public final class MyString {
//字符串数组,由于是final,所以在构造方法中就得赋值
private final char[] value;
//缓存hash
private int hash;
//无参构造
public MyString() {
this.value = "".toCharArray();
}
//字符串构造
public MyString(String str) {
this.value = str.toCharArray();
}
//字符数组构造
public MyString(char[] value) throws MyException {
//校验
if(value == null) throw new MyException("您传空值干嘛呀");
//深拷贝
char[] newVal = new char[value.length];
for(int i = 0; i < value.length; i ++) {
newVal[i] = value[i];
}
this.value = newVal;
}
//字符串数组指定位置构造
public MyString(char[] value, int offset, int length) throws MyException {
//校验
if(value == null) throw new MyException("您传空值干嘛呀");
if(offset < 0 || length < 0) throw new MyException("您的offset和length不能为负数");
if(offset >= value.length) throw new MyException("您的offset太大了啊");
if(offset + length >= value.length) throw new MyException("您的length太大了啊");
//深拷贝
char[] newValue = new char[length];
for(int i = 0; i < length; i ++) {
newValue[i] = value[offset + i];
}
this.value = newValue;
}
public MyString(byte[] ascii) throws MyException {
//校验
if(ascii == null) throw new MyException("您的字节数组不能为null");
//深拷贝
char[] newAscii = new char[ascii.length];
for(int i = 0; i < newAscii.length; i ++) {
newAscii[i] = (char) ascii[i];
}
this.value = newAscii;
}
public MyString(int[] value) throws MyException {
//校验
if(value == null) throw new MyException("您的unicode数组不能为空");
//深拷贝
char[] newValue = new char[value.length];
for(int i = 0; i < value.length; i ++) {
newValue[i] = (char) value[i];
}
this.value = newValue;
}
public int length() {
return this.value.length;
}
public boolean isEmpty() {
return this.value.length == 0;
}
public char charAt(int index) throws MyException {
if(index < 0 || index >= this.value.length) throw new MyException("您要找寻的位置越界了");
return this.value[index];
}
//返回unicode码
public int codePointAt(int index) throws MyException {
if(index < 0 || index >= this.value.length) throw new MyException("您要找寻的位置越界了");
return this.value[index];
}
public boolean equals(Object obj) {
if(obj == this) return true;
if(obj instanceof MyString) {
MyString newMyString = (MyString) obj;
if(newMyString.length() != this.value.length) return false;
char[] newValue = newMyString.value;
for(int i = 0; i < newValue.length; i ++) {
if(newValue[i] != this.value[i]) return false;
}
}
return false;
}
public int hashCode() {
if(hash == 0) {
//hash
int h = 0;
//无需考虑溢出问题,31时处理速度更快,左移5位-h
for (char c : value) {
h = 31 * h + c;
}
hash = h;
}
return hash;
}
public MyString substring(int start, int end) throws MyException {
//校验
if(start < 0 || start >= value.length) throw new MyException("您的start不合法");
if(end < start || end > value.length) throw new MyException("您的end不合法");
char[] newValue = new char[end - start];
for(int i = start; i < end; i ++) {
newValue[i - start] = value[i];
}
return new MyString(newValue);
}
public MyString concat(MyString myString) throws MyException {
//校验
if(myString == null) throw new MyException("您的myString不能为空");
char[] newValue = myString.value;
char[] resValue = new char[value.length + newValue.length];
for(int i = 0; i < value.length; i ++) {
resValue[i] = value[i];
}
for(int i = value.length; i < resValue.length; i ++) {
resValue[i] = newValue[i - value.length];
}
return new MyString(resValue);
}
//重写Object里面的方法
//当打印一个普通对象的时候,例如System.out.println(obj),其实是执行了System.out.println(obj.toString())
//所以仿写一个String类,toString方法是必不可少的
//但是toString方法是继承自Object,返回值是String无法更改
//所以说仿写的String类也只能借助真正的String来实现
//至于为什么真正的String类的toString方法中return this就可以返回真正的像""这种字符串可能是底层将""将String类进行了某种关联
public String toString() {
return new String(value);
}
}
MyException
package mystring;
public class MyException extends Exception {
public MyException() {
super();
}
public MyException(String msg) {
super("【MyString Exception】: " + msg);
}
}