[toc]
== 和 equals 的对比
== 是一个比较运算符
1、== : 既可以判断类型,又可以判断引用类型
2、== :判断基本类型,判断的是值是否相等
3、== :如果是引用类型,判断的是地址是否相等,即判定是不是同一个对象
equals
1、equals :是object 类中的方法,只能判断引用类型,
2、equals :默认判断的是地址是否相等,子类中往往重写该方法(public boolean equals(object obj) ) 用于判断内容是否相等,
Java hashCode
1、提高具有哈希结构的效率
2、两个引用,如果指向的是同一个对象,则哈希值肯定是一样的!
3、两个引用,如果指向的是不同对象,则哈希值是不一样的
4、哈希值主要根据地址号来的!,不能完全将哈希值等价于地址
5、集合中hashCode 按需重写
Java 的动态绑定机制
B 是 A 的子类 , A a = new B()
a 在编译类型是 A (等号左边) ,运行类型是 B (等号右边)
1、当调用对象的方法的时候,该方法会和该对象的内存地址进行绑定
2、当调用对象属性时,没有动态绑定机制,哪里有声明,哪里使用
接口
implements 实现接口
extends 继承
1、JDK 7.0 以前,接口里的所有方法都没有方法体,即都是抽象方法
2、JDK 8.0 后,接口可以有静态方法,默认方法,也就是说接口中可以有方法的具体实现(default 关键字修饰)
3、一个类可以实现多接口 implements A ,B
4、接口中的属性,只能是final的。而且是 public static final
5、接口中属性的访问形式 : 接口明. 属性名
6、接口不能继承其他类,但是可以继承多个别的接口
7、接口的修饰符 只能是 public 和 默认,这点和类的修饰符是一样的
代码块
1、static 代码块也叫静态代码块,作用就是对类进行初始化,而且他随着类的加载而执行,并且只会执行一次。如果是普通代码块,没创建一个对象,就执行一次。
2、类什么时候被加载【需要背】
- 1、创建对象实例时(new)
- 2、创建子类对象实例,父类也会被加载
- 3、使用类的静态成员时(静态属性、静态方法)
3、普通代码块,在创建累的实例时,会被隐式调用。被创建一次,就会被调用一次。如果只是使用类的静态成员时,普通代码块并不会被调用
note:
1、staitc 代码块是在类加载时执行,且只会执行一次
2、普通代码块是在创建对象时调用的,创建一次就会调用一次
3、类加载的三种情况,需要记住!!!
创建一个类时,在一个类 调用的顺序是:(重点,难点)
1、调用静态代码块和静态属性初始化(注意:静态代码块和静态属性初始化调用的优先级是一样的,如果有多个静态代码块和多个静态变量初始化,则按着他们的定义顺序进行调用)
2、调用普通代码块和普通属性初始化方法(注意:普通代码块和蒲绒属性调用的优先级是一样的,按定义顺序调用)
3、调用构造方法
创建一个子类(继承关系),他们的静态代码块,静态属性初始化,普通代码块,普通属性初始化,构造方法的调用顺序如下:
1、父类的静态代码块和静态属性,按顺序执行
2、子类的静态代码块和静态属性,按顺序执行
3、父类的普通代码块和普通类属性,按执行顺序执行
4、父类的构造方法
5、子类的普通代码块和普通类属性,按顺序执行
6、子类的构造方法
静态、非静态 方法调用
静态代码块只能直接调用静态成员(静态属性和静态方法),普通代码块可以调用任意成员
内部类
一个类内部又完整嵌套了另一个类结构。被嵌套的类称为内部类,嵌套其他类的类称为外部类。使我们类的第五大成员【五大成员:
属性、方法、构造器、代码块、内部类】,内部类最大特点就是可以直接访问私有属性,并且可以体现类与类之间的包含关系
class Outer { // 外部类
class Inner{ // 内部类
}
}
class Other{ // 其他类
}
内部类分类
定义在外部类局部位置上(比如方法上)
package com.zhao.smallchange;
public class Outer {
private int age = 23;
public static void main(String[] args) {
new Outer().innerAction();
}
public void innerAction(){
class innerClass{
private int age = 12;
public void sayAge(){
System.out.println("内部类age:" + age + "外部类age:" + Outer.this.age );
}
}
innerClass innerClass = new innerClass();
innerClass.sayAge();
}
}
-
1、局部内部类 (有类名)
-
1、局部内部类是定义在外部类的局部位置,通常在方法、代码块中
-
2、可以直接访问外部类的多有成员,包含私有的
-
3、不能添加访问修饰符,但是可以使用final修饰
-
4、作用域: 仅仅在定义它的方法或者代码块中
-
5、局部内部类可以直接访问外部类的成员,比如 方法和属性
-
6、外部类在方法中,可以创建 内部类 对象,让后调用方法即可
-
7、外部其他类 不能访问 局部内部类 (因为 内部类地位是一个局部变量)
-
8、如果外部类和局部内部类成员变量重名时,默认遵循就近原则,如果想访问外部类的成员变量,则可以使用 (外部类名.this.成员) 去访问
2、匿名内部类(没有类名,重点!!)
new 类或者接口(参数列表){
类的相关实现
};
// 实际使用
package com.zhao.smallchange;
public class Outer {
public static void main(String[] args) {
new Outer().innerAction(new OuterInterface() {
@Override
public void sayHello() {
System.out.println("我是匿名内部类");
}
});
}
public void innerAction(OuterInterface subInterface){
subInterface.sayHello();
}
}
interface OuterInterface{
public void sayHello();
}
定义在外部类的成员位置上
package com.zhao.smallchange;
public class Outer {
private int n1 = 10;
public String name = "张三";
public static void main(String[] args) {
new Outer().t1();
}
class InnerClass{
public void say(){
System.out.println("n1 = " + n1 + " name =" + name);
}
}
public void t1(){
InnerClass innerClass = new InnerClass();
innerClass.say();
}
}
1、成员内部类(没有static修饰)
- 1、可以直接访问外部类的成员变量,包含私有
- 2、可以添加任意访问修饰符( public、protected、默认、private ),因为它的地位就是一个成员。
- 3、作用域 : 和外部类的其他成员一样,为整个类
- 4、成员内部类 --> 访问外部类成员 ,直接访问
- 5、外部类 --> 访问内部类,创建内部类对象,并访问
- 6、其他外部类 --> 访问 --> 成员内部类
- 6.1、第一种方式
public static void main(String[] args) { InnerClass innerClass = new Outer().new InnerClass(); }
- 6.2、第二种方式,通过一个方法返回内部类对象
public static void main(String[] args) { InnerClass innerClass1 = new Outer().getInnerClass(); } public InnerClass getInnerClass(){ return new InnerClass(); }
-7、如果内部类成员变量 和 外部类成员变量 冲突,外部类还是 外部类.this.成员变量
2、静态内部类(使用static修饰)
class Outer10{
private int n1 = 10;
private static String name = "张三";
static class Inner10{
}
}
1、放在外部类成员位置
2、使用 static 修饰
3、可以访问外部类的所有成员变量,包含私有的,但不能直接访问非静态变量
4、可以添加任意访问修饰符 (public、protected、默认 、private),但是不能直接访问非静态成员变量
// 第一种: 对象调用
package com.zhao.smallchange;
public class StaticInnerClass01 {
public static void main(String[] args) {
Outer10.Inner10 inner10 = new Outer10.Inner10();
}
}
class Outer10{
private int n1 = 10;
private static String name = "张三";
static class Inner10{
}
}
// 第二种: 普通方法暴露
package com.zhao.smallchange;
public class StaticInnerClass01 {
public static void main(String[] args) {
Outer10.Inner10 staticInnerClass = new Outer10().getStaticInnerClass();
}
}
class Outer10{
private int n1 = 10;
private static String name = "张三";
static class Inner10{
}
public Inner10 getStaticInnerClass(){
return new Inner10();
}
}
// 第三种:static 方法
package com.zhao.smallchange;
public class StaticInnerClass01 {
public static void main(String[] args) {
Outer10.Inner10 staticInnerClass = Outer10.getStaticInnerClass();
}
}
class Outer10{
private int n1 = 10;
private static String name = "张三";
static class Inner10{
}
public static Inner10 getStaticInnerClass(){
return new Inner10();
}
}
5、作用域 整个类
6、如果外部类和静态内部类的成员重名是,静态内部类访问的时候,默认遵循就近原则,如果想访问外部类的成员,则可以使用 (外部类.成员)去访问
String、StringBuilder、StringBuffer 选择
- 1、如果字符串存在大量的修改操作,一般使用StringBuilder 和 StringBuffer
- 2、如果字符串存在大量的修改操作,并在单线程情况下,使用StringBuilder
- 3、如果字符串存在大量的修改操作,并在多线程情况下,使用StringBuffer
- 4、如果我们字符串很少修改,被多个对象引用,使用String。比如配置信息
random 随机数
返回的是 0 <= x < 1 之间的随机小数
- 1、[2 7] 随机整数 (int)(a + Math.random() * (b - a + 1))
- 2、[2 7) 随机整数 (int)(a + Math.random() * (b - a))
public static void main(String[] args) {
// 思考:请写出获取 a, b 之间的一个随机整数,a = 2 b = 7
// 1、 [0 10) 随机数
System.out.println("=========[0 10) 随机数===========");
for (int i = 0; i < 10; i++) {
System.out.println(10 * Math.random());
}
// 2、 [0 10) 随机整数
System.out.println("=========[0 10) 随机整数===========");
for (int i = 0; i < 10; i++) {
double random = Math.random();
System.out.println(10 * random);
System.out.println((int)(10 * random));
}
// 3、[2 12) 随机整数
System.out.println("=========[2 12) 随机整数===========");
for (int i = 0; i < 10; i++) {
double random = Math.random();
System.out.println(10 * random + 2);
System.out.println((int)((12 - 2) * random + 2));
}
// 4、[2 7) 随机整数
System.out.println("=========[2 7) 随机整数===========");
for (int i = 0; i < 10; i++) {
double random = Math.random();
System.out.println(5 * random + 2);
System.out.println((int)((7 - 2) * random + 2));
}
// 5、[2 7]随机整数 == [2 8)随机整数
System.out.println("=========[2 7] 随机整数===========");
for (int i = 0; i < 10; i++) {
double random = Math.random();
System.out.println((8 - 2) * random + 2);
System.out.println((int)((1 + (7 - 2)) * random + 2));
}
集合实现类的选择
-
1、一组对象:Collection 接口
- 允许重复:List
增删多:LinkedList 底层维护了一个双向链表
改查多:ArrayList 底层维护 Object类型的可变数组 - 不允许重复:Set
无序:HashSet 底层是HashMap,维护了一个哈希表 即(数组 + 链表 + 红黑树)
排序:TreeSet
插入和取出顺序一致:LinkedHashSet,维护数组 + 双向链表
- 允许重复:List
-
2、一组键值对
- 1、键无序:HashMap 底层是: 哈希表 jdk7: 数组 + 链表 jdk8:数组 + 链表 + 红黑树
- 2、键排序:TreeMap
- 3、键插入和取出顺序一致:LinkedHashMap
- 4、读取文件 Properties
Thread 和 Runnable
- 1、从Java 设计上来看,通过继承Thread或者实现Runnable 接口来创建线程本质上是没有区别的,Thread 类本身就实现了 Runnable 接口
- 2、实现Runnable 接口方式更加适合多个线程共享一个资源的情况,并且避免了继承的限制
package com.zhao.learn01;
public class Learn {
public static void main(String[] args) {
T3 t3 = new T3();
Thread thread1 = new Thread(t3);
Thread thread2 = new Thread(t3);
thread1.start();
thread2.start();
}
}
class T3 implements Runnable{
@Override
public void run() {
// 进行线程操作
}
}
线程常用方法
- 1、setName : 设置线程名称,使之与参数name相同
- 2、getName:返回该线程的名称
- 3、start:使该线程开始执行;java虚拟机底层调用线程 start0 方法
- 4、run:调用线程对象 run 方法
- 5、setPriority:更改线程优先级
- 6、getPrority:获取线程优先级
- 7、sleep:在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)
- 8、interrupt :中断线程
- 9、yield:线程的礼让,让出CPU让其他线程执行。但是礼让时间不确定,所以也不确定成功
- 10、join:线程的插队,插队线程一旦插队成功,则肯定先执行完插入线程的所有任务
note:
- 1、start 底层会创建新的线程,并调用run,run就是一个简单的方法调用,不会启动新的线程
- 2、线程优先级范围
- 3、interrupt,中断线程,但没有真正的结束线程。所以一般用于中断正在休眠的线程
- 4、sleep 线程的静态方法,使当前线程休眠
网友评论