类的内部结构

属性、方法、构造器、代码块、内部类


代码块

代码块又可以称为初始化块,属于类的一个成员,它是将逻辑语句封装在方法体中。
通过{ }包裹。代码块没有方法名,没有参数,没有返回值,只有方法体
它是不需要通过对象或类进行显式的调用,会在类加载或者创建对象时,主动地(隐式)调用

静态代码块

一个类被加载时会被调用一次,做一些初始化的工作(只要类被加载就会被执行)

static {
    code;
}

实例代码块

每次创建实例都会被调用一次,用的很少(创建对象就调用一次
可以有多个静态块,但是开发中一般就写一个静态块

{
    code;
}

面试题

父类优于子类,静态块优于其他
父类输出顺序:静态块 > 实例块 > 构造器
子类输出顺序(父类有静态块、实例块和构造器,子类也有静态块、实例块和构造器)

当没有继承关系时,就一个类,静态块——实例块——构造器
当有继承关系时,父类静态块——子类静态块——父类实例块——父类构造器——子类实例块——子类构造器


static关键字

static静态(类属性,类方法)可以修饰属性、方法、代码块
static修饰的结构,不属于任何一个对象

修饰属性时,输出用 类名.属性名(不依赖于对象,没有对象也能用)
public class Test(){
    static String name = "UserName";

    public static void main(String [] args) {
        System.println.out(Test.name);
    }
}
修饰方法时,输出用 类名.方法名
public class Ch03 {

    static String name = "里奥·梅西";

    public static void show(){
        System.out.println("静态方法...");
    }

    public static void main(String[] args) {
        Ch03.show();
    }
}

内存解析

静态的变量或者静态方法存在于方法区,静态的结构不会被垃圾回收
不属于某一个实例对象,只存在于方法区。调用静态结构,直接用 类名.的方式。

Java与C语言的区别

Java面向对象,C面向过程
Java有垃圾回收,C没有垃圾回收

静态结构和非静态结构

实例方法和静态方法的互相调用:

  1. 静态方法中不可以直接调用实例方法,如果想用,必须对象.方法名
  2. 实例方法可以直接调用静态方法

静态的结构加载,随着类的加载而加载。
非静态的结构,随着对象的创建而加载。

在Java中调用实例方法,必须要有主体(必须要有对象去调)。方法不是一等公民,不能直接调用。
静态方法无论在哪里都是类名.方法名的形式来进行调用,同一个类的静态方法之间可以省略类名。

接口中的常量默认public static final
开发中,基本上常量的声明都是public static final
Arrays.toString( )、Arrays.sort( )、Integer.parseInt( )、String.valueof( ) ——都是静态方法


this和super

无论是this还是super,都不可以在静态结构中使用。
this可以代表子类对象,super什么都不代表
this.方法 super.方法

静态结构是属于类的,静态结构是优先于对象就存在的
thissuper必须有对象才能出现,必须得有实例。
静态结构包括代码块也包括代码


外部类

类的外边可以再声明一个类 (尽量不用)

public class Test(){
    code;
}

class Other(){
    code;
}

一个public声明的类,类名必须和.java的文件名相同
外部类就是两个类

类的组成结构:
属性、方法、构造器、代码块、内部类


内部类

在一个类内部进行其他类结构的嵌套操作
我们之前写过的链表,Node类其实主要就是SuperLinked
我们可以把Node类定义在SuperLinked
public class Ch01 {
    static {
        System.out.println(“load static class”);
    }
    public class Inner {
    }
    public static class InnerStatic {
    }
    public static void main(String[] args) {
    }
}

设计模式

设计模式是人们为软件开发中抽出可重复利用的解决方案。
软件开发工程师之间沟通的“行话”

面向对象的设计原则

  1. 开闭原则(Open Close Principle),对扩展开放,对修改关闭(继承,实现接口),我们可以通过“抽象约束,封装变化”来实现开闭原则。通过接口或者抽象类为软件定义一个相对稳定的抽象层,将相同的可变因素封装在相同的具体实现类中。
  2. 里氏代换原则,子类继承父类时,除了添加新的方法完成新增的功能外,尽量不要重写
  3. 依赖倒转原则,要面向接口编程,不要面向实现(类)编程
    a.每个类尽量提供接口或抽象类,或者两者兼备
    b.变量的类型声明尽量是接口或者是抽象类
    c.任何类都不应该从具体类派生
    d.在使用继承时,要遵循里氏代换原则
  4. 接口隔离原则,使用多个隔离的接口
  5. 迪米特法则
  6. 合成复用原则
  7. 单一原则:一个类只做一件事

单例模式

一个类只能有一个实例

饿汉式单例模式
不管以后会不会使用到,该实例化对象,先创建了再说(很着急)
实现的办法就是直接new实例化

懒汉式单例模式(延迟加载)
什么时候调用getInstance这个方法,什么时候再初始化(new)

懒汉式

public class Ch04 {
    private static Ch04 ch04;
    private Ch04(){
    }
    public static Ch04 getInstance()  {
        if(ch04 == null){
            // xcxxxxx
            ch04 = new Ch04();
        }
        return ch04;
    }
}

注意

这种懒汉式在多线程环境中完全错误的,根本不能保证是单例的状态

内部类实现单例
也是懒汉式的一种,这种懒汉式没有线程的问题
public class Ch05 {
    private Ch05(){
    }
    public static Ch05 getInstance() {
        return SingletonHolder.INSTANCE;
    }
    private static class SingletonHolder {
        private static final Ch05 INSTANCE = new Ch05();
    }
}

结合了饿汉式和懒汉式的优点
只要不调用getInstance方法,就不会使用内部类
内部类一旦被使用一次只会被初始化一次,以后一直用的是INSTANCE静态常量


箭头函数

JDK8的新特性
函数式接口:如果一个接口只有一个抽象方法,这个接口就成为函数式接口
可以用注解@DunctionalInterface标识

常规操作

public class Ch06 {
    public static void test(Inter01 inter01) {
        System.out.println(inter01.show());
    }

    public static void main(String[] args) {
        Inter01 inter01 = new Impl01();
        test(inter01);
    }
}

非常规操作

public static void main(String[] args){
    Inter01 inter01 = new Inter01(){
        @Override
        public String show(){
            return "the class nicked override show() function";
        }
    };
    test(inter01);
}

简化操作

public static void main(String[] args){
    test(new Inter01() {
        @Override
        public String show() {
            return "Override";
        }
    });
}

箭头函数

public static void main(String[] args) {
    test((I,j) -> {return i+","+j;});
}
这个结构可以分为三部分
第一部分,小括号包裹形参,类型不要
第二部分,->
第三部分,->重写的方法体

当重写的方法体只有一句话时,可以精简到这种程度
-> "override str"
当重写的方法只是有一句返回值时,可以精简到这种
test(() -> "override str");

总结箭头函数

1.有参数,有返回值
(i+j) -> {
    return i+j;
}

如果方法体只是一句返回值(i , j) -> i + j

2.有参数,无返回值
(i,j) -> {
    code;
}

如果方法体只有一句话(i , j) ->

最后修改:2023 年 01 月 09 日
如果觉得我的文章对你有用,请随意赞赏