JAVA课堂笔记(一)

JAVA编译器:

1. protable:一次编译,多次运行,平台独立

“.java“在运行程序的时候不需要,在编译阶段由编译器编译成".class"文件,再由不同版本的java虚拟机解释成不同平台上的native code

平台独立的原因:存在一种中间代码(.class,字节码)

2. 为了避免for这类语句的多次重复解释(耗时),java编译器中有个just-in-time compiler,使这一段编译后直接放到java虚拟机的内存中,而不是硬盘上的.class文件中。当然,每次重新编译程序的时候还是要重新编译。

3. 编译生成的.class文件的个数取决于class的个数,而不是文件的个数。

数据类型与包装类

如Integer是个类(包装类),int是个关键字。

具有自动装箱和拆箱的功能。

public static void f(int i){...;}    //f的参数类型为int

int i = 0;
Integer ii = i;   //自动装箱
f(ii);     //ii为包装类的对象,自动拆箱

除char类型对应包装类为”Character“,int类型对应包装类为”Integer“,其他类型对应的包装类名称都是将它们的首字母大写。

在Java中,只有String类和包装类是immutable的类,即不可变的类(创建完后不能更改)。若要更改,则是产生一个新的对象再赋给原来的引用。

枚举类型

一个枚举类不能new出新的对象,相当于它的构造函数也是private的。

enum Direction{East, West, North, South};    //Direction为一个枚举类

//若
public void turnDirection(Direction d){...}
//则方法turnDirection只能传入以上4种值之一,否则编译器会报错

栈(stack)、堆(heap)、Class类对象的存放等

栈:

栈(stack)的数量 = 线程的数量

堆(heap):只有一个

变量variable:可以在栈中或者在堆中(以及Class类的对象中,static)

引用reference:可以在栈中或者在堆中(以及Class类的对象中,static)

对象:堆中(以及Class类的对象中,static)

f(){
    Student s1 = new Student();    //把对象的地址赋给了s1
}

s1是一个引用,在f中(f在栈中)开辟了一块地方存s1(引用),对象实体new Student() 在heap中。

Class类对象的存放:

Class类:java.lang.Class类

Class类的构造函数是私有的,因此不能显式地创建一个Class类的对象(私有构造函数later->)

private Class(ClassLoader loader) {
        classLoader = loader;
}

Java中,加载一个类定义的.class文件也是作为一个对象存放在内存中,这个对象由Class Loader(Class 类)创建。

ClassLoader在加载一个.class文件中的类定义时,才能自动创建一个这样的对象。这个对象不在堆中,也不在栈中。Java有一个专门的地方用来存放Class类对象。

垃圾回收

Java虚拟机判断是否为垃圾:

1. 引用计数:当stack中的引用被销毁,没有引用指向heap中的对象时,该对象被回收。

存在的问题:当heap中的多个对象荷香引用(指向)时,引用不为0,但因都没有来自stack的引用,本应都为垃圾,但没有被回收。(如下图右)

2. 类似于重力:

若该断没断,则对象不能掉入“垃圾场”,不能被回收。

Java中对象都在堆中,就算有GC(自动清理),也可能发生memory leak。

static

1. static类变量

static类变量(静态初始化):存放在Class类的对象中。在加载A类定义、创建Class类的对象时被初始化。只初始化一次(前提:方法区不做垃圾回收)

非static成员变量(构造初始化):存放在堆中的对象中。实际上是在每个重载的构造函数中初始化。每次重新调用构造函数都要创建一个新的。

class A{
    int a;    //非static成员变量
    static int i;    //static类变量

    A(){}        //相当于  A(){int a; ...}
    A(int p){}    //相当于  A(int p){int a; ...}
}

static与非static的区别在于:存放的位置不同

2. static类方法

对于方法而言,不管是否为static,它的可执行代码都在Class类的对象里面。它们的区别在于是否有“this”。

在内存中有一个方法区(Method Area),用来放方法的可执行代码(区别于heap)

static与非static的区别在于:有没有"this"

例:现有非static方法f(),static方法g()

public void f(){
    g();    //可以调用,g不需要this而f有,不影响使用
}

public static void g(){
    //f();       不能调用,因为f需要this而g没有
}

3. static对象

static Hello h =  new Hello();

//若不再想使用它时,应显式地
h = null;

 若定义了一个static的对象,则当不再想使用它时,应显式地将它赋为null。

private构造函数

单例(singleton pattern):如果希望一个类只有一个对象,则把构造函数声明为private,然后直接创建一个static对象给用户使用。(如:一个windows系统只希望有一个回收站对象)

多例:同理单例,直接创建多个static对象给用户使用(如:方向类只有东南西北四个对象)

public class Hello{
    public static void main(String[] args){
        Person p1 = Person.getPerson();    //调用getPerson方法获取Person类对象
    }
}
class Person{
    private static Person p = new Person();    //私有静态对象
    private Person(){}        //私有构造函数
    
    public Person getPerson(){    //公有函数获取静态对象
        return p;
    }
}

重载(overload)与重写(override)

重载(overload):由编译器决定调用哪个版本的重载函数,叫做早绑定(earlybind)

重写(override):在运行时(run-time)决定,叫做晚绑定(latebind)

如何判断两个对象的值是否相等

“Object”类提供了equals()方法,但这个方法本身与“==”没有区别,需要自己去重写

//A类中,由成员变量i

public boolean equals(Object obj){
    return i == obj.i;
}

猜你喜欢

转载自blog.csdn.net/qq_42182367/article/details/82800280