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最相近的整型整数