java运行机制

JDK:Java Development Kit (开发者工具包)

JDK ⊃ JRE ⊃ JVM

内存和内存地址

内存:软件在运行过程中,临时存储的数据

内存地址:内存会以字节(1byte)为单元,划分成很多区域,每个区域对应一个编号

地址范围:(会转化为16进制,方便阅读)

基本数据类型:栈内存直接存值

应用数据类型:栈内存中存储值的索引

数组

1. 存储为连续的空间

2. 一旦定义,长度不变

静态初始化数组

遍历数组

int[] ageArr1 = new int[]{1, 2, 3, 4, 5, 6};

for (int i = 0; i < ageArr1.length; i++) {
    System.out.println(ageArr1[i]);
}

for (int j : ageArr1) {
    System.out.println(j);
}

动态初始化

默认初始化的值

方法

// 代码结构
public static 返回值类型 方法明(参数1, 参数2) {
    方法逻辑
    return 返回值;
}

// 示例
public static int sum(int a, int b) {
    int result = a + b;
    return result;
}

方法的重载

1. 方法名相同
2. 但各自的(形参)参数不同【个数不同,类型不同,顺序不同,都算】
称为方法重载(`Overload`)。
public static void myHello() {
    System.out.println("你好");
}

public static void myHello(String name) {
    System.out.println("你好,我是" + name);
}

public static void myHello(String name, int age) {
    System.out.println("你好,我是" + name + "我今年" + age);
}

不构成方法的重载,重载只看方法名和参数

public static void myHello() {
    System.out.println("你好");
}

public static String myHello() {
    return "你好";
}

面向对象(一种编程思想)

class和instance class类,就相当于模具, instance实例,就相当于模具中生产的东西

测试类和javabean类

javabean类 (描述一类事物)

package classStuden;

public class People {
    // 属性
    String name;
    int age;
    // 行为,方法
    public void say() {
        System.out.println("我是人类");
    }
}

测试类(带有main方法,是程序的主入口)

package classStuden;

public class Test {
    public static void main(String[] args) {
        People p1 = new People();
        p1.say();
    }
}

工具类 (帮我们做事情的类,如求最大值啊之类的)

public class ArrayUtil {
    // 私有化构造方法,目的:不让外界创建构造函数
    private ArrayUtil() {
    }

    //获取数组的平均值
    public static void getAverage(int[] arr) {
        int sum = 0;
        int length = arr.length;
        for (int j : arr) {
            sum += j;
        }
        System.out.println("该数组的平均值是:" + sum * 1.0 / length);
    }
}

访问控制修饰符【权限修饰符】(4 个)

public String name;
protected String sexy;
int age; // 没有修饰符,默认就是default
private int score;

不控制访问权限,而是定义特性、状态、行为,比如静态、不可变、抽象等。

static 关键字

不属于对象,属于类

在class里,定义共享数据,无论哪个实例化对象修改了这个值,所有实例化对象的值都会被修改**(所有对象共享)**

静态变量是随着类加载而加载的,优先于对象出现的(也就是说,类还没有实例化之前,静态变量就在堆内存中开辟空间了)

public class Student {
    static String teacher;
    String name; // 成员变量
    int age;

    // 构造方法
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void getTeacherName() {
        System.out.println("老师的名字是:" + Student.teacher);
    }
}

public class Test {
    public static void main(String[] args) {
        Student s1 = new Student("小明", 18);
        Student s2 = new Student("小红", 20);

        Student.teacher = "张雪峰";

        s1.getTeacherName(); // 输出:张雪峰
        s2.getTeacherName(); // 输出:张雪峰
    }
}

static 修饰静态方法

静态方法多用在测试类和工具类中,javabean类很少使用

public class StaticUtil {
    String name; // 大名
    static String xiaoName; // 小名

    int age; // 岁数
    int virtualAge; // 虚岁

    public void getName() {
      // 可以访问所有变量和方法
    }

    public static void getXiaoName() {
    //    只能访问静态变量(xiaoName, virtualAge)和静态方法(getVirtualAge)
    }

    public void getAge() {
    }

    public static void getVirtualAge() {
    }
}

final 关键字(不可变 / 不可修改 / 不能被覆盖)相当于JS里面的 const

this关键字

用于区分成员变量和局部变量的

public class Student {
    String name; // 成员变量

    public void setName(String name) { // 局部变量(参数)
        // 这里 this.name = 成员变量
        // 这里 name = 传入的参数
        this.name = name;
    }
}
public class Student {
    String name; // 成员变量
    int age;

    // 构造方法
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void getName() {
        String name = "局部名称";
        // 就近原则
        System.out.println("局部变量的名称" + name);
        // 获取成员变量
        System.out.println("成员变量的名称" + this.name);
    }
}
public class Test {
    public static void main(String[] args) {
        Student s1 = new Student("小明", 18);
        Student s2 = new Student("小红", 20);

        s1.getName(); // 此时this指向s1这个地址
        s2.getName(); // 指向s2的地址
    }
}

构造方法,构造函数

构造方法的特点:

  • 必须和类名一样,且不写的时候,会默认帮你创建一个无参数的构造方法
  • 如果写了任意构造方法,系统不再提供无参数的构造方法
  • 构造方法也可以重载
  • 没有返回值类型,也没有void
  • 没有具体返回值,也不能写return

构造方法的执行时机:

  • 创建对象时,由虚拟机调用,不能手动调用
  • 每创建一次对象,就会调用一次构造方法
public class People {
    // 属性
    public String name;
    protected String sexy;
    int age;
    private int score;
    
    public People() {
    }

    public People(String name, String sexy, int age, int score) {
        this.name = name;
        this.sexy = sexy;
        this.age = age;
        this.score = score;
    }
}

People p1 = new People("cmh","男", 18, 100);

枚举(枚举类,特殊的类)

public enum 枚举类名 {

    // 属性

    // 方法
    
}
public enum SeasonEnum {
    // 这里其实都是相当于使用 new 实例化出来的对象,调用的就是下面的 SeasonEnum 构造方法,
    // 所以在使用的时候,直接使用【类名.枚举值】的形式就可以了,不需要再new了
    // 且这里的枚举值,默认都是使用 【 public static final 】 修饰的
    SPRING(1, "春天"),
    SUMMER(2, "夏天"),
    AUTUMN(3, "秋天"),
    WINTER(4, "冬天");


    // 枚举可以有成员变量
    private final int code;
    private final String name;

    // 构造方法(默认就是 private,且必须是private,不能 public)
     SeasonEnum(int code, String name) {
        this.code = code;
        this.name = name;
        System.out.println("构造函数被执行了:" + this.name); // 会发现直接输出四个
    }

    // 可以写普通方法
    public String getInfo() {
        return code + ":" + name;
    }
}

面向对象的三大特征(封装、继承、多态)

继承 extends

什么是继承

继承的目的

继承的重要规则

什么是重写

super 关键字(继承必备)

public class Student extends  People {
    
    // 可以把多个子类中的方法,提取到父类中去,提高代码的复用性
    // 子类可以在父类的基础上,增加其他功能,使子类更强大

}

多态(事物的多种形态)

什么是多态

多态的前提条件(必须同时满足)

public class Animal {
    // 父类方法
    public void shout() {
        System.out.println("动物叫");
    }
}
public class Dog extends Animal {
    // 重写父类方法
    @Override
    public void shout() {
        System.out.println("汪汪汪");
    }
}
public class Cat extends Animal {
    // 重写父类方法
    @Override
    public void shout() {
        System.out.println("喵喵喵");
    }
}
public class Test {
    public static void main(String[] args) {
        // 多态:父类引用 指向 子类对象
        Animal animal1 = new Dog();
        Animal animal2 = new Cat();

        // 同一个方法 shout(),执行结果不同!
        animal1.shout(); // 输出:汪汪汪
        animal2.shout(); // 输出:喵喵喵
    }
}

多态现象

多态的作用(为什么要用它?)

多态中成员变量 / 静态方法的特点(面试常考)

class Animal {
    String name = "动物";
    public static void sleep(){
        System.out.println("动物睡");
    }
}

class Dog extends Animal {
    String name = "小狗";
    public static void sleep(){
        System.out.println("小狗睡");
    }
}

// 测试
Animal a = new Dog();
System.out.println(a.name); // 动物(变量无多态)
a.sleep(); // 动物睡(【静态方法】无多态)

多态的向上转型与向下转型

  1. 向上转型(自动发生)

父类 引用 = new 子类();

就是我们上面写的多态,安全、自动

  1. 向下转型(强制转换)

目的:把 “伪装成父类” 的子类对象,变回子类本身,从而调用子类独有的方法和属性

必须配合instanceof判断,否则会报类型转换异常。

抽象类(abstract)

抽象类就是:被设计成 “专门用来被继承、不能直接 new” 的半完成类。

它的作用就是强制子类必须重写抽象方法,不带abstract关键字的方法可以不用重写。

1. 关键字:abstract

  • 抽象类:abstract class
  • 抽象方法:abstract void 方法名(); 没有方法体
// 抽象类
public abstract class User {
    String name;

    // 抽象方法:只有声明,没有实现
    public abstract void work(参数);
}

抽象类到底用来干嘛?(核心作用)

接口(Interface)

特点:

// 先 extends 继承,再 implements 实现多个接口
public class Student extends Person implements Study, Work {

    // 实现接口1的方法
    @Override
    public void study() {
        System.out.println("学生在学习");
    }

    // 实现接口2的方法
    @Override
    public void work() {
        System.out.println("学生的工作是学习");
    }
}

接口的成员特点:

// 接口
public interface Animal {
    // 方法默认就是 public abstract
    void shout();
}

// 实现类
public class Dog implements Animal {
    @Override
    public void shout() {
        System.out.println("汪汪汪");
    }
}

接口和接口之间可以继承,也可以多继承

// 接口1
interface A {
    void testA();
}

// 接口2
interface B {
    void testB();
}

// 接口3
interface C {
    void testC();
}
// D 接口同时继承 A、B、C 三个接口
interface D extends A, B, C {
    void testD();
}

JDK8和JDK9之后的扩展

内部类

成员内部类

public class Outer {
    private int a = 10;

    // 成员内部类
    class Inner {
        public void show() {
            // 直接访问外部类私有变量
            System.out.println(a);
        }
    }
}

创建步骤

Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.show();

静态内部类(static 修饰)

public class Outer {
    private static int b = 20;

    // 静态内部类
    static class StaticInner {
        public void show() {
            System.out.println(b);
        }
    }
}

创建步骤

Outer.StaticInner inner = new Outer.StaticInner();

局部内部类(方法里的类)

public class Outer {
    public void method() {
        int num = 100;

        // 局部内部类
        class LocalInner {
            public void show() {
                System.out.println(num);
            }
        }

        // 只能在方法内创建对象
        LocalInner inner = new LocalInner();
        inner.show();
    }
}

匿名内部类(最重要!开发大量用)

父类或接口 对象名 = new 父类或接口() {
    // 必须重写所有抽象方法
    @Override
    public void 方法名() {
        // 方法体
    }
};
  • 没有类名,所以叫 “匿名”

  • 只能创建一个对象,用完就丢

  • 可以直接访问外部类的所有成员(包括 private)

  • 可以访问方法里的变量,但变量必须是 final 或 有效 final

  • 本质就是:快速创建子类 / 实现类对象

匿名内部类示例:

先定义一个接口:

interface Study {
    void study();
}

不用匿名内部类(传统写法,有名字的实现类)

class Student implements Study {
    @Override
    public void study() {
        System.out.println("学生在学习");
    }
}

// 使用
Study s = new Student();
s.study();

用匿名内部类(一步搞定)

Study s = new Study() {
    @Override
    public void study() {
        System.out.println("学生在学习");
    }
};

s.study();

为什么这里可以使用接口实例化,其实不是实例化,

【 这里其实是在创建一个 “匿名的、实现了 Study 接口的子类对象”,并用这个匿名的实现类进行实例化的 】

为什么可以直接用Study s来接收实例化?

【 这其实是多态的体现 --> 父 父 = new 子() / User user = new Student()

本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:alixiixcom@163.com