language包
继承 封装 多态
类 对象
修饰符 : 4个访问修饰符 static final abstract
构造方法
继承
接口
完成一件事情的时候,考虑需要哪些对象,然后再去找对象的类,由这个类创建出对象,完成任务。类可以是jre提供的、导入别人定义的类、自己定义的。找到类有 创建出对象,后面使用对象,通过点运算符去调用对象里面的功能。 如果一个功能使用很频繁,每次使用的时候都需要创建对象,为了方便可以将这个功能设计为静态的,则使用的时候不需要创建对象,直接类名.功能 就可以使用。即任何一个java程序里面都默认有一行代码:import java.lang.*;
java提供了很多类,然后将这些类分别不同的包中,将功能相近的类放在同一个包中。比如util包里面放入的都是工具类,net包里面放的都是网络相关的类。。。写程序的时候如果需要用到java提供的类,将这个类导入到当前的程序里面 import。
lang包就是java的语言包,是使用最多的一个包,一般的任何一个程序都会使用到这个包里面的东西。所以java为了方便些程序,每个java程序里面默认都引入了这个包里面的所有类,即当写程序的时候使用到lang包里面的东西,不需要去使用import引入。
Object
Object类是所有java类的根类,即任何一个类,如果不停的去点击父类,最后都会回到Object类。或者java中任何一个类都有父类,除了Object。
java中任何一个类,如果定义的时候没有显示的去extends另一个类,这时系统默认的给它一个父类Object。即一个类没有定义父类,则它的父类就是Object类。 则Object类里面定义的方法,在java的任何一个类里面都有。
如果一个对象想要被克隆,则它的类在定义的时候需要标记,或者需要一个能被克隆的身份。
Object中的hashCode本身没有实现
1、对于基本数据类型的包装类,其值就是其本身
2、对于String类型的HashCode,也是String自己实现的,其算法目的是尽可能减少哈希冲突。
3、对于自定义类,需要自己重写hashCode,如果不重写,就在程序运行过程中,JVM根据内存地址自动分配。(根据每个有意义的属性值,计算各自的hashCode相加等一系列得到)
浅克隆
如果一个对象在实际的使用中经常被复制一个新的出来,就可以考虑在设计类的时候重写Object的clone方法,将clone方法的访问修饰符修改为public,当前类实现Cloneable接口。(Cloneable和特殊,它里面没有方法,就是一个标记。)
浅克隆只关注当前对象,如果当前对象有属性也是复合类型,则这个属性没有被克隆一个新的出来。即浅克隆出来的对象,会将原对象的基本类型的属性复制一个新的,复合类型的属性都是用以前的。
深克隆
克隆一个对象的时候,它的属性也被克隆,不管属性是基本类型还是复合类型。
public class Dog implements Cloneable{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Dog(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Dog() {
super();
}
public Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
}
public class Teacher implements Cloneable{
private String name;
private int age;
private Dog dog;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
public Teacher() {
super();
}
public Teacher(String name, int age, Dog dog) {
super();
this.name = name;
this.age = age;
this.dog = dog;
}
public Teacher(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Object clone() throws CloneNotSupportedException {
Teacher t = (Teacher)super.clone();
//将当前对象的dog属性克隆一个新的,赋给t对象
Dog d = (Dog)this.dog.clone();
t.setDog(d);
return t;
}
}
equals
对象如果使用 == 判断 相等,则判断的是对象在内存中的地址,与数组一样。(只要是复合类型, == 判断的都是内存中的地址。) 如果是判断复合类型中的值,则需要通过方法来判断。
如果需要判断两个对象是否一样,Object中定义了equals方法,约定以后只要判断对象是否一样,都统一的使用equals方法,但Object中的equals方法源代码还是使用了==符号。 即这个方法需要重写。
//创建对象 比较对象是否相等
//比较内存相等 或比较值相等
Student stu1 = new Student(1001,"小黑",10);
Student stu2 = new Student(1001,"小黑",10);
System.out.println(stu1==stu2);//地址不同,返回false
System.out.println(stu1.hashCode()==stu2.hashCode());//重写了hashCode方法,返回true
System.out.println(stu1.equals(stu2));//若Student类未重写equals方法,是判断地址是否相等
//由于equals本身没有办法解决
//两个对象因id和name相等业务上是同一个对象的问题
//所以需要重写equals和hash
//为什么要重写HashCode呢?
//答:在JMV中如果HashCode不相等,一定不能认为是同一个对象
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof Student) {
Student stu = (Student) obj;
if (this.id == stu.id && this.sname.equals(stu.sname)) {
return true;
}
}
return false;
}
@Override
public int hashCode() {
return id;
}
String类
一个不可变的字符序列。 Class类在JVM装载过程中,会分配一个存放字符串的常量池,在类加载时先检查常量池中是否有"abc"常量,如果有就直接引用该常量,如果没有则创建一个新的对象。 String是一个复合类型,很多特征像基本类型。String可以通过new创建,有可以直接给一个String变量赋值。
String字符串是一个常量,即一旦创建就不能更改它的值,
String s = "abc";
s = s + "d";
System.out.println(s);
//内存里面会有之前的abc字符串 还有新的abcd字符串
String s1 = "abc";
String s2 = "abc";
String中的构造方法很多,即可以通过很多方法创建String对象。
byte[] b ---->String对象 new String(b)
String对象s ----> 字节数组byte[] s.getBytes()
char[] c ----->String 对象 new String(c)
String对象s -----> char[] s.toCharArray();
String s = "abc" 与 Strinig s = new String("abc")
String s = "abc" 内存中创建了一个字符串对象
Strinig s = new String("abc") 创建了两个字符串对象
String 中常用的方法:
s.length() : 返回字符串的长度
s.charAt(index) : 获取字符串s的第index位置的字符,返回的是字符。index可以看成下标,范围从0开始到字符 串的长度减1结束 0 <= index <= s.length()-1 。 超过这个长度 就会有字符串下标越界
s.compareTo(s2) : 比较两个字符串的大小。返回的是整数。正数代表s大,负数代表s2大。
s.concat(s2) : 将s2拼接到s的后,生成一个新的字符串,原字符串不变 等同于+的功能
s.contains(s2): 判断s中是否包含字符串s2,返回boolean类型
s.endsWith(s2) : 判断字符串s是否以字符串s2结尾 返回boolean类型
s.startsWith(s2):判断字符串s是否以字符串s2开始 返回boolean类型
s.equals(Object o) : 判断传过来的o是否是一个字符串且与s中的值一样。(判断两个字符串是否一样,不能使用 ==号,应该使用equals方法)
s.equalsIgnoreCase(s2) : 忽略大小写判断s与s2是否一样。
s.indexOf(s2) : 返回s2 在s中第一次出现的位置 (s2 可以是字符串也可以是字符),如果s中不包含s2子字符串, 则返回-1.
s.lastIndexOf(s2) : 返回s2在s中最后一次出现的位置
s.isEmpty() : 判断s是否是空字符串,不是null,而是"" 即 长度是0;
s.replace(s1,s2) : 将字符串s中的所有s1子字符串用字符串s2替换,生成一个新的字符串,原字符串不变。 s2替 换s中所有的子字符串s1.
s.split(s2) : 使用s2将字符串s拆开,返回的是一个字符串数组,原字符串不变(s2是一个正则表达式)
如果s2在s的最开始位置,则拆的结果中第一个子字符串是空字符串
例如:有字符串s "aaa123aaa456aaa789aaa1111" 如果使用字符串"aaa"去拆字符串s,则得到的一个字符串数组{ "","123","456","789","1111" }
s.substring(int n) : 从字符串s的第n个位置开始,截取后面所有的子字符串。
例如: s=“abcdef” ; s.substring(2) --->cdef
s.substring(n,m) : 从字符串s的第n个位置开始截取到第m个位置,包含第n个位置,不包含第m个位置,原字符串 不变,返回一个新的字符串。
s.toLowerCase() : 将字符串s中的所有大写字母转成小写字母,原字符串不变,生成一个新的字符串。
s.toUpperCase() : 转大写
s.trim() : 去掉字符串s两边的空格,不包含中间的空格
String.valueOf(x) : String的静态方法,将x转成字符串。
StringBuffer
线程安全的可变字符序列,即可变的字符串,String是不可变的字符串,对String的任何操作都没有改变原字符串,都是生成了一个新的字符串。StringBuffer的任何操作都没有生成新的字符串,都是在原字符串进行修改。
构造方法:
new StringBuffer()
new StringBuffer(int n)
new StringBuffer(String str)
String s转成StringBuffer ---> new StringBuffer(s)
StringBuffer sb转String ----> sb.toString()
StringBuffer中的方法
sb.length() : 获取sb的长度(里面字符的数量)
sb.toString() : 将StringBuffer转String
sb.append(x) : 将x拼接到sb的后面,(x可以是任何类型) 类似于String中的concat方法,但concat方法不改 变原字符串,append是在原字符串上面修改。
sb.charAt(index) : 获取sb的第index位置上的字符
sb.delete(n,m) : 删除sb中从第n个位置到第m个位上的字符,在原字符串修改
sb.indexOf(x) : 获得x在sb中第一次出现的位置
sb.lastIndexOf(x) : 获取x在sb中最后一次出现的位置
sb.insert(index, x) : 将x插入到sb的第index位置上。 (x可以是任何数据) 在原字符串上修改。
sb.replace(n,m,x) : 将sb中从第n个位置到第m个位置结束,中间的内容使用x替换
例: StringBuffer sb = new StringBuffer("abcdef") sb.replace(1,3,"hello")
则sb就变成: ahellodef
sb.reverse() : 将sb反转。
sb.substring(n,m) : 截取,在原字符串截取
sb.setCharAt( index, c ) : 将sb中的第index位置上的字符修改为c
StringBuilder
一个可变的字符序列。与StringBuffer的功能(方法) 一模一样。但StringBuffer是线程安全的即同步的, Stringbuilder是线程不安全的,即非同步。所以在使用的时候StringBuilder比StringBuffer快,效率高。
(一)结论:
(1)速度比较:String < StringBuffer < StringBuilder
(2)String的处理速度比StringBuffer、StringBuilder要慢的多。
(二)String的处理速度为什么要比StringBuffer、StringBuilder慢的多?
- String是不可变的对象
- StringBuffer是可变对象
- StringBuilder是可变对象
请结合上面的代码理解这个问题:
(1)String本身就是一个对象,因为String不可变对象,所以,每次遍历对字符串做拼接操作,都会重新创建一个对象,循环100万次就是创建100万个对象,非常的消耗内存空间,而且创建对象本身就是一个耗时操作,创建100万次对象就相当的耗时了。
(2)StringBuffer和StringBuilder只需要创建一个StringBuffer或StringBuilder对象,然后用append拼接字符串,就算拼接一亿次,仍然只有一个对象。
(三)是不是可以抛弃使用String,转而使用StringBuffer和StringBuilder呢?
答案是否定的。
上文的总结只是针对于数据量比较多的情况,但是数据量比较少的情况呢?
我们分析一下代码:
(1)String遍历代码:一开始定义一个String常量(创建一个String对象), 再开始遍历;
(2)StringBuffer代码:一开始定义一个String常量(创建一个String对象)和一个创建StringBuffer对象,再开始遍历;
(3)StringBuiler代码:一开始定义一个String常量(创建一个String对象)和一个创建StringBuiler对象,再开始遍历;
(2)和(3)比(1)多了一个创建对象流程,所以,如果数据量比较小的情况建议使用String。
(四)是StringBuffer和StringBuilder的区别?
- StringBuffer是线程安全的
- StringBuilder是非线程安全的, 这也是速度比StringBuffer快的原因
(五)使用场景
(1)如果要操作少量的数据用 String
(2)单线程操作字符串缓冲区 下操作大量数据 StringBuilder
(3)多线程操作字符串缓冲区 下操作大量数据 StringBuffer
System
System代表系统,使用最多的是它的out属性中的print方法: System.out.println();
System类不能实例化,无法获取构造方法。它提供的都是静态的方法,不需要创建对象。
3个属性:
PrintStream err
PrintStream out
InputStream in
常用的方法:
System.currentTimeMillis() : 返回 从1970、1、1到 此时时间的毫秒数. 返回的是一个long的数据
System.arraycopy(a,i,b,j,l) : 复制数组,将a数组中从i个位置开始复制l个长度到b数组中
System.exit(0) : 终止整个程序的运行 (停止一个循环 break 终止一个函数return)
System.gc() : 强转jvm 垃圾回收(不需要手动调用)
包装类
java中世界万物皆对象,一个基本类型的数据也应该是一个对象,既然是一个对象,就有对象所属于的类型。
java中每个基本类型都可以封装成对应的复合类型:
byte ---> Byte
short ---> Short
char ---> Character
int --> Integer
long ----> Long
float ---> Float
double----> Double
boolean ---> Boolean
Integer
int对应的复合类型是Integer。
-
对于 -128<=Integer的值 <=127之间,装箱时不会创建新对象,而是直接引用常量池中的值。如:
Integer n1 = 100;
Integer n2=100;
n1.equals(n2)//返回值为true -
如果超出该范围,则自动创建新对象,各自指向新对象的内存。
创建Integer对象:
new Integer(int x)
new Integer(String s) ---> s字符串里面是一个整数
转换:
基本类型int ---> 复合类型Integer : newInteger(x)
复合类型的Integer-----> 基本类型int : 调用Integer的invalue() 方法
方法:
x.compartTo(y) : 比较两个Integer对象 x和y 哪个大,如果整数表示x大,如果是负数表 示y大。0表示两个相等。
x.equals(y) : 判断x与y是否相等
Integer.parseInt(s) ---> 将字符串s转成int值
Inreger中有静态的方法可以方便的将10进制的数字转2进制、8进制、16进制,返回的是一个字符串:
String str = Integer.toBinaryString(x); 将x转2进制
String str = Integer.toOctalString(x); 将x转8进制
String str = Integer.toHexString(x); 将x转16进制
3个类型的转换: int String Integer
int--->String : +"" 或者 String.vlaueOf(int x)
String--->int : Integer.parseInt(String s)
String ----> Integer : new Integer(String s)
Integer---->String : in.toString()
int ---> Integer : new Integer(int x)
Integer----> int : in.invalue()
Dobule
3个转换 double Double String
double---> Double : new Double(double d)
Double---> double : d.doubleValue()
Double---->String : d.toString()
String ---> Double : new Double(String s)
double ---> String : +"" 或者 String.valueOf(double d)
String ---> double : Double.parseDouble(String s)
浙公网安备 33010602011771号