Java 点滴

[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,维护数组 + 双向链表
  • 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 线程的静态方法,使当前线程休眠
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容