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)