【java学习】类Class

1,概念

1)类对象

java用new来新建对象,它会存放在堆中。

String a1 = new String("abc");
String a2 = new String("abc");
String a3 = new String("abcd");

如上,总共创建了2个String对象。
“abc””abcd”在类加载的时候各创建1各,执行代码的时候a1,a2,a3分别创建3个实现。

2)类和数组的区别

类是方法和变量的集合体。
数组是相同类型的无序数据的集合。

2,内部类

1)静态内部类

使用static修饰的内部类。
①静态内部类可以有静态成员,而非静态内部类则不能有静态成员。
②静态内部类的非静态成员可以访问外部类的静态变量,而不可访问外部类的非静态变量。
③非静态内部类的非静态成员可以访问外部类的非静态变量。

2)内部类

①为什么内部类会持有外部类的引用?

内部类虽然和外部类写在同一个文件中, 但是编译完成后, 还是生成各自的class文件,内部类通过this访问外部类的成员。因为内部类的产生依赖于外部类,持有的引用是.this。
原理:
i>编译器自动为内部类添加一个成员变量, 这个成员变量的类型和外部类的类型相同, 这个成员变量就是指向外部类对象(this)的引用;
ii> 编译器自动为内部类的构造方法添加一个参数, 参数的类型是外部类的类型, 在构造方法内部使用这个参数为内部类中添加的成员变量赋值;
iii>在调用内部类的构造函数初始化内部类对象时,会默认传入外部类的引用。

3)匿名内部类

使用new生成的内部类。

①什么Java里的匿名内部类只能访问final修饰的外部变量?

匿名内部类用法:

public class TryUsingAnonymousClass {
    public void useMyInterface() {
        final Integer number = 123;
        System.out.println(number);

        MyInterface myInterface = new MyInterface() {
            @Override
            public void doSomething() {
                System.out.println(number);
            }
        };
        myInterface.doSomething();

        System.out.println(number);
    }
}

编译后的结果:

class TryUsingAnonymousClass$1
        implements MyInterface {
    private final TryUsingAnonymousClass this$0;
    private final Integer paramInteger;

    TryUsingAnonymousClass$1(TryUsingAnonymousClass this$0, Integer paramInteger) {
        this.this$0 = this$0;
        this.paramInteger = paramInteger;
    }

    public void doSomething() {
        System.out.println(this.paramInteger);
    }
}

因为匿名内部类最终用会编译成一个单独的类,而被该类使用的变量会以构造函数参数的形式传递给该类,例如:Integer paramInteger,如果变量 不定义成final的,paramInteger在匿名内部类被可以被修改,进而造成和外部的paramInteger不一致的问题,为了避免这种不一致的情况,因为Java 规定匿名内部类只能访问final修饰的外部变量。

3,抽象类

1)概念

2)抽象类与接口的区别

抽象类与接口都用于抽象,接口是对动作的抽象,抽象类是对根源的抽象。
抽象类表示的是,这个对象是什么。多用于在同类事物中有无法具体描述的方法的场景,当父类与子类之间存在逻辑上的层次结构时使用。
接口表示的是,这个对象能做什么。多于不同类之间,定义不同类之间的通信规则。
抽象类和接口不能被实例化。(因为有抽象方法未实现)
优先选用接口,尽量少用抽象类 。
区别如下:

①继承

接口可以多重继承,抽象类不可以。

②实现

实现接口的一定要实现接口里定义的所有方法,而实现抽象类可以有选择地重写需要用到的方法。
当子类为抽象类时,继承抽象类,可以实现抽象方法,也可以不实现。

③定义

接口定义方法,不能实现(不能有函数体),而抽象类可以实现部分方法。
抽象类可以有构造方法,接口没有构造方法.

④数据类型

接口是公开的,里面不能有私有的方法或变量,是用于让别人使用的,而抽象类是可以有私有方法或私有变量的。接口中基本数据类型的数据成员,都默认为static和final(这意味着在定义接口的时候,就要给这些变量赋值,且以后不能修改),抽象类则不是。
接口只能有抽象方法喝final类型的成员变量,所以不能定义构造方法。

4,类的加载

1)动态连接和静态解析

①动态连接

在类运行期间才能确定某些目标方法的直接引用。

②静态解析

在类加载阶段或第一次使用时转化为直接引用。
成立的前提是:方法在程序真正执行前就有一个可确定的调用版本,并且这个方法的调用版本在运行期是不可改变的。
被 invokestatic 和 invokespecial 指令调用的方法,都可以在解析阶段确定唯一的调用版本。
主要有:①静态方法;②私有方法;③实例构造器;④父类方法四类。这些方法可以称为非虚方法(还包括 final 方法),与之相反,其他方法就称为虚方法(final 方法除外)。
这里要特别说明下 final 方法,虽然调用 final 方法使用的是 invokevirtual 指令,但是由于它无法覆盖,没有其他版本,所以也无需对方发接收者进行多态选择。Java 语言规范中明确说明了 final 方法是一种非虚方法。

5,Object类

1)概念

Object类是层次结构的根,所有类都继承这个类。
Object类是java语言中唯一没有父类的类。
在不明确给出超类的情况下,Java会自动把Object作为要定义类的超类。

2)方法

①Object()

默认构造方法

②clone()

创建并返回此对象的一个副本。

③equals(Object obj)

指示某个其他对象是否与此对象“相等”。在Object中与==是一样的,子类一般需要重写该方法。

④finalize()

当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。

⑤getClass()

final方法,返回一个对象的运行时类。

⑥hashCode()

返回该对象的哈希码值。
该方法用于哈希查找,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到。

⑦notify()

唤醒在此对象监视器上等待的单个线程。

⑧notifyAll()

唤醒在此对象监视器上等待的所有线程。

⑨toString()

返回该对象的字符串表示。转换成字符串,一般子类都有重写,否则打印句柄。
这个字符串的格式是固定的:类名@hashcode。这个hashcode是一串数字(16进制),在Java中叫句柄/(虚拟)地址。但是句柄不是内存地址

⑩wait

使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。
–wait()
直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。
–wait(long timeout)
直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量。
–wait(long timeout, int nanos)
直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量。

6,Math类

1)取整

static double ceil(double a);
返回>=a的min整数
static double floor(double a);
返回<=a的max整数,类型未double
static double rint(double a);
四舍五入,返回与a最相近的整数
static long round(double a);
四舍五入,返回与a最相近的长整型整数。将原来的数字加上0.5后再向下取整。例:

Math.round(12.5) = 13;
Math.round(-12.5) = -12

static int round(float a);
四舍五入,返回与a最相近的整型整数

猜你喜欢

转载自blog.csdn.net/sunshinetan/article/details/79626201