Java基础篇

父类子类构造函数

子类的构造函数会隐式调用父类的无参构造函数,子类若想调用父类的构造函数需在子类的构造函数的第一行使用super调用父类的构造函数。

public class Person {

    private String name;

    public Person() {
        System.out.println("无参构造");
    }

    public Person(String name) {
        this.name = name;
        System.out.println("构造函数");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

public class Student extends Person {
    private String sex;
    private String age;

    public Student() { }

    public Student(String name, String sex, String age) {
        super(name);
        this.sex = sex;
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
String、StringBuffer、StringBuilder

String字符串存储在字符串常量区,任何对String进行的修改都会产生一个新的对象,String是final的
StringBuffer和StringBuilder都是可变的,可以对同一个对象进行修改。区别是StringBuilder是线程不安全的,线程使用StringBuffer时会先对其加锁。

类不允许多继承,接口允许多继承

CopyOnWriteArrayList适用于写少读多的并发场景。
ReadWriteLock即为读写锁,他要求写与写之间互斥,读与写之间互斥,读与读之间可以并发执行。在读多写少的情况下可以提高效率。
ConcurrentHashMap是同步的HashMap,读写都加锁。

volatile只保证多线程操作的可见性,不保证原子性。

一个线程执行的过程有三个阶段:
加载(复制)主存数据到操作栈 --> 对操作栈数据进行修改 --> 将操作栈数据写回主存
volatite关键字,让编译器不去优化代码使用缓存等,以保证线程在“加载数据阶段”加载的数据都是最新的
eg:
某一时刻i=6是最新的值,volatile保证线程A,B都同时加载了这个最新的值,
然后A执行i(A)+1=7,然后将7写回主存,
B也执行i(B)+1=7,然后也将7写回内存,
这样,执行两次加法,i却只增加了1

静态分配与动态分配

分配是针对方法而言的,指的是方法确定的过程,根据发生实际分为静态分配和动态分配。
相关的非虚方法和虚方法
非虚方法:指的是在解析阶段可以确定方法的唯一版本,符合的有静态方法、私有方法、构造器、final方法。
虚方法:非私有方法。

静态分配的典型例子是方法的重载。

Person a = new Student()可以这样来理解,Person是变量a的静态类型,Student是变量a的实际类型,a的静态类型在编译期间就可以确定,而a的实际类型只有在运行期间才可以确定。
对于方法重载而言,方法的签名及方法名都一样,只能通过形参去确定,而形参是在编译期间就能确定的静态类型,即方法重载是通过静态分配确定的。

/**
 * 静态分派
 *
 */
public class StaticDispatch {
        
    static class Human {
         
    }
     
    static class Man extends Human {
         
    }
     
    static class Women extends Human {
         
    }
    
    public void sayHello(Human guy) {
        System.out.println("hello, guy!");
    }
     
    public void sayHello(Man guy) {
        System.out.println("hello, man!");
    }
     
    public void sayHello(Women guy) {
        System.out.println("hello, women!");
    }
     
    
    public static void main(String[] args){
        
        Human man = new Man(); 
        Human women = new Women();
         
        StaticDispatch sd = new StaticDispatch();
        sd.sayHello(man);   
        sd.sayHello(women);
 
    }
 
}

动态分配与另一个特征息息相关,重写
/**
 * 动态分派
 *
 */
public class DynamicDispatch {
        
    static abstract class Human {
        protected abstract void sayHello();
    }
    
    static class Man extends Human {
        
        @Override
        protected void sayHello() {
            System.out.println("hello man!");
        }        
    }
     
    static class Women extends Human {
     
        @Override
        protected void sayHello() {
            System.out.println("hello women!");
        }        
    }
     
    
    public static void main(String[] args){
        
        Human man = new Man();
        Human women = new Women();
         
        man.sayHello();
        women.sayHello();
        
        man = new Women();
        man.sayHello();
 
    }
 
}

其输出会是

hello man!
hello women!
hello women!
类加载过程

加载 ——验证——准备——解析——初始化
加载:通过类的全限定名来获取类的二进制字节流,将字节流的静态存储结构转化为方法区的运行时数据结构,在内存中生成一个代表这个类的java.lang.Class对象作为方法区这个类的各类数据的访问入口。
验证:确保Class文件的字节流符合当前虚拟机的要求,文件格式验证、元数据验证、字节码验证、符号引用验证。
准备:为类变量分配内存并且初始化。
解析:
初始化:执行类构造器()

静态块,非静态块,构造方法执行顺序

静态块——非静态块——构造方法

public class StaticBlockTest {

    {
        System.out.println("normal test");
    }

    static {
        System.out.println("static test");
    }

    public StaticBlockTest() {
    }

    public static void main(String[] args) {
        StaticBlockTest test = new StaticBlockTest();

        StaticBlockTest another = new StaticBlockTest();
    }

}

输出结果:

static test
normal test
normal test

another example

public class StaticBlockingTest {

    {
        System.out.println("构造块");
    }

    public static StaticBlockingTest a = new StaticBlockingTest();

    public static  StaticBlockingTest b = new StaticBlockingTest();

    static {
        System.out.println("静态构造块");
    }

    public StaticBlockingTest() {
        System.out.println("构造函数");
    }

    public static void main(String[] args) {
        StaticBlockingTest c = new StaticBlockingTest();
    }
}

输出结果

构造块
构造函数
构造块
构造函数
静态构造块
构造块
构造函数

其结果与其顺序有关

一个类的构造器可以调用该类的其他构造方法
public class Student extends Person {
    private String sex;
    private String age;

    public Student() {
    }

    public Student(String sex) {
        this.sex = sex;
    }

    public Student(String age, String sex) {
        this(sex);
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}
引用传递
public class Tester{
public static void main(String[] args){
   Integer var1=new Integer(1);
   Integer var2=var1;
   doSomething(var2);
   System.out.print(var1.intValue());
   System.out.print(var1==var2);
}
public static void doSomething(Integer integer){
    integer=new Integer(2);
    }
}

输出

1true
image.png

你可能感兴趣的:(Java基础篇)