实体类:在现实世界中能找到实际的个体
JavaBean(或PoJo,Domain)是一种特殊类
Javabean可以理解成实体类,其对象可用于在程序中封装数据。可以将其多个对象再封装到集合类中存储。
标准Javabean须满足以下要求:
所有类的超类,其中方法所有类都可调用。
== 和 equals 的对比:
==既可判断基本类型,又可判断引用类型。如果判断基本类型,判断的是值是否相等;如果判断引用类型,判断的是地址是否相等,即判定是不是同一个对象。
equals:Object类中方法,只能判断引用类型
默认判断的是地址是否相等,子类中往往重写该方法,用于判断内容是否相等(如:String类中重写equals,用于判断字符串内容是否相同)
"abc".equals("abc"); //true
可仿照equals方法源码,在自定义类中重写,重写equals的内部仍可应用原本的equals方法判断
public boolean equals(Object anObject) {
if (this == anObject) {
return true; //如果是同一对象,直接返回true
}
if (anObject instanceof String) { //是此类才比较
String anotherString = (String)anObject; //向下转型,因为要用到anObject的属性
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
返回对象的哈希码值(十进制)。
对象名.hashCode()
特点:
返回该对象的字符串表示
默认返回:全类名(包名+类名)+@+哈希值的十六进制
子类往往重写toString方法,用于返回对象的属性信息
重写toString方法,打印对象或拼接对象时,都会自动调用该对象的toString形式
当直接输出一个对象时,toString方法会被默认的调用
System.out.println(对象);
等同于调用输出
对象.toString()
针对八种基本数据类型相应的引用类型,就是包装类(Wrapper)。有了类的特点,就可以调用类中的方法
基本数据类型 | 包装类 |
---|---|
boolean | Boolean |
char | Character |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
其中Byte、Short、Integer、Long、Float、Double都是Number类的子类,Number和Boolean、Character都是Object的子类
装箱:基本数据类型 —> 包装类
拆箱:包装类 —> 基本数据类型
jdk5前的手动装箱和拆箱
//手动装箱 int -> Integer
int n1 = 100;
Integer integer = new Integer(n1);
Integer integer1 = Integer.valueOf(n1);
//手动拆箱 Integer -> int
int i = integer.intValue();
jdk5后(含jdk5)的自动装箱和拆箱
自动装箱底层调用的是valueOf方法,如Integer.valueOf()
int n1 = 100;
Integer integer = n1; //可直接赋值,本质不变
int n2 = integer;
包装类 —> String:
Integer i = 100;
String str1 = i + "";//i仍是Integer
String str2 = i.toString();
String str3 = String.valueOf(i);
String —> 包装类:
String str = "123";
//parseInt方法
Integer i = Integer.parseInt(str);//使用到自动装箱
//创建对象
Integer i1 = new Integer(str);//用构造器
Integer类:
Integer.MIN_VALUE 返回最小值
Integer.MAX_VALUE 返回最大值
String是字符串类型,可以定义字符串变量指向字符串对象。用Unicode字符编码。字符串内容用String中的属性 private final char value[];
存放字符串内容
String类实现了Serializable接口,说明String可以串行化(串行化意味着对象可以在网络传输);实现了Comparable接口,说明了String对象可以比较
String是final类,创建的字符串对象(地址)不可改变," “方式给出的字符串对象,在堆中的字符串常量池中存储。每次修改其实是产生并指向了新的字符串对象,原对象没有改变
eg:下面输出name为ABCD,但字符串常量池中存有"AB"和"CD”,name指向相加的结果
String name = "AB";
name += "CD";
System.out.println(name);
new String(char[] a,int startIndex,int count)
String s1 = new String();
String s2 = new String("ABC"); //前两种几乎不用
char[] chars = {'A','B','C'};
String s3 = new String(chars);
byte[] by = {97,98,99,65,66,67};
String s4 = new String(by); //转成字符串输出
区别:
char[] chars = {'A','B','C'};
String s3 = new String(chars);
String s2 = "ABC";
System.out.println(s2 == s3); //s2,s3指向不同
输出false
System.out.println(s2.equals(s3)); //比较字符串值
输出true
System.out.println(s2 == s3.intern()); //s3指向堆,s3.intern指向常量池
输出true
System.out.println(s3 == s3.intern());
输出false
Person p1 = new Person();
p1.name = "abc";
Person p2 = new Person();
p2.name = "abc";
System.out.println(p1.name == p2.name);
//p1,p2是不同对象,但其中的name属性均指向常量池中的abc,所以相同
输出true
System.out.println(p1.name == "abc");
//属性在堆中存储,指向常量池,与"abc"指向相同
输出true
String s1 = new String("abc");
String s2 = new String("abc");
System.out.println(s1 == s2);
//s1,s2都指向常量池中同一地址,但s1,s2本身是两个对象,地址不同
输出false
String s2 = new String("ABC");//实际上创建了两个对象,在常量池和堆区中,s2指向堆区中的
String s1 = "abc"; //实际上创建了0个对象,因为原本要在常量池创建,但已有重复字符串,s1指向常量池中的
//s1 != s2
字符串相加的实现:
" "常量相加在池中
String s1 = "abc";
String s1 = "a"+"b"+"c";
//Java存在编译优化机制,编译时"a"+"b"+"c"会转化为"abc",提高运行性能
//反编译可验证
s1 == s2 true!!!
变量相加在堆中
String s1 = "hello";
String s2 = "abc";
String c = s1 + s2;
c指向堆中的value,value指向池中的"helloabc"(相当于用new String创建的对象)
toString()方法的底层就是new String对象
用==判断会出错,因为" “创建的对象指向常量池,输入的字符串指向堆区
可用String类提供的equals比较
equalsIgnoreCase可忽略大小写比较
String name = "abc";
String name1 = "ABC";
name.equals(name1); //return false
name.equalsIgnoreCase(name1); //return true
toUpperCase、toLowerCase、compareTo与char相同。
遍历字符串中字符:
String str = "ABCDE";
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
System.out.println(ch);
}
intern() 方法:
intern() 方法返回字符串对象的规范化表示形式。
它遵循以下规则:对于任意两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true。
返回值:字符串常量池中与传入对象内容相同的字符串地址。若无相同的,则将此String对象添加到池中,并返回此对象的引用
indexOf:获取字符在字符串中第一次出现的索引,从0开始,找不到则返回 -1
lastIndexOf:获取字符在字符串中最后一次出现的索引,从0开始,找不到则返回 -1
trim:去前后空格
concat:拼接字符串,可连续拼接
String s1 = s1.concat("abc").concat("def");
format:格式化字符串%s、%c、%d、%f
String类每次更新、拼接需要重新开辟空间,效率较低,StringBuilder和StringBuffer可增强String的功能,提高效率。
StringBuffer代表可变的字符序列,可对字符串内容进行增删(长度可变),StringBuffer是一个容器
StringBuffer本身是final类,不可被继承。在StringBuffer的父类AbstractStringBuilder中有属性 char[] value(不是final),存放字符串内容,因此存放在堆中。StringBuffer的增删不用每次都创建新对象,更高效
String —> StringBuffer
String s = "hello";
//方式一:使用构造器
StringBuffer b1 = new StringBuffer(s);
//方式二:使用append方法
StringBuffer b2 = new StringBuffer();
b2.append(s);
StringBuffer —> String
//方式一:使用toString方法
String s1 = b1.toString();
//方式二:构造器
String s2 = new String(b1);
append()
delete(start,end)
replace(start,end,string)
将[start,end)间的内容替换indexOf()
查找子串在字符串第一次出现的索引insert(index,string)
在index处插入string,原索引为index的内容自动后移length()
一个可变的字符序列,此类提供一个与StringBuffer兼容的API,但不保证同步(不是线程安全的)。该类被设计用作StringBuffer的一个简易替换。
StringBuilder的方法没有做互斥的处理,即没有synchronized关键字,因此用在字符串缓冲区被单个线程使用的时候。如果可能,建议优先用此类,因为在大多数实现中,它比StringBuffer快。
StringBuilder中主要操作为append和insert方法,可重载这些方法以接受任意类型的数据
String s = "a"; s +="b";
丢弃了原对象,产生了字符串"ab",s指向新对象"ab"。多次改变串内容,会导致大量副本字符串对象留在内存中,降低效率。
对字符串做大量修改不要用String。很少修改,被多个对象引用使用String(如配置信息)