Java三大特性——封装、继承和多态
封装就是将类的信息隐藏在类内部,不允许外部程序直接访问,而是通过该类的方法实现对隐藏信息的操作和访问。
继承反映类与类的层级关系,是提高代码复用的一种方式。
多态性:所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编译时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。
访问控制
- 让客户端程序员无法触及到他们不应该触及的部分;
- 允许库设计者可以改变内部工作方式而不用担心会影响到客户端程序员。
代码复用与UML图
- 复用的两种方式:组合(has-a)和继承(is-a);
- 组合允许在不改变现有客户端代码时,修改成员对象,比继承有很大的灵活性。编译器必须对通过继承而创建的类施加编译时限制。
- Unified Modeling Language
1、使用工具:Visio或者processon在线作图
2、类图:类和接口
3、关系:泛化(Generalization), 实现(Realization),关联(Association),聚合(Aggregation),组合(Composition),依赖(Dependency)
泛化是一种继承关系:带三角形箭头指向父类;
实现是类与接口的关系:带三角箭头的虚线,箭头指向接口;
关联是一种拥有的关系,它使一个类知道另一个类的属性和方法:实线或普通箭头指向被拥有者。
聚合是整体与部分关系,且部分可离开整体而单独存在:带空心菱形的实心线,菱形指向整体;
组合是整体与部分关系,但部分不能离开整体而单独存在,带实心菱形的实线,菱形指向整体;
依赖是一种使用的关系,即一个类的实现需要另一个类的协助:带箭头的虚线,指向被使用者。
单根继承结构
- 单根继承结构保证所有对象都具备某些功能;
- 同时使垃圾回收器的实现变得容易得多。
Object
参考链接:https://www.cnblogs.com/lwbqqyumidi/p/3693015.html
1、private static native void registerNatives();
在JVM中注册Object类中的本地方法
2、protected native Object clone() throws CloneNotSupportedException;
clone函数返回的是一个引用,指向的是新的clone出来的对象,此对象与原对象分别占用不同的堆空间。
public class Example {
public static void main(String[] args) {
Object obj = new Object();
//编译错误:The method clone() from the type Object is not visible
Object obj2 = obj.clone();
}
}
protected修饰的属性或方法表示:在同一个包内或者不同包的子类可以访问。"不同包中的子类可以访问",是指当两个类不在同一个包中的时候,继承自父类的子类内部且主调(调用者)为子类的引用时才能访问父类用protected修饰的成员(属性/方法)。在子类内部,主调为父类的引用时并不能访问此protected修饰的成员。!(super关键字除外)
public class Example {
public static void main(String[] args) {
Example example = new Example();
try {
Example e2 = (Example)example.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
// 运行异常
// java.lang.CloneNotSupportedException: Example
clone()的正确调用是需要实现Cloneable接口,如果没有实现Cloneable接口,并且子类直接调用Object类的clone()方法,则会抛出CloneNotSupportedException异常。
public class Example implements Cloneable {
public static void main(String[] args) {
Example example = new Example();
try {
Example e2 = (Example)example.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
3、public final native Class<?> getClass();
getClass()也是一个native方法,返回的是此Object对象的类对象/运行时类对象Class<?>。效果与Object.class相同。
三种获取Class对象的方式:类名.class、对象.getClass()和Class.forName(类全名).
class Example {
static {
System.out.println("类初始化");
}
}
public class Test {
public static void main(String[] args) {
Class<Example> cls = Example.class;//无任何输出
}
}
class Example {
static {
System.out.println("类初始化");
}
}
public class Test {
public static void main(String[] args) {
try {
Class<Example> cls = (Class<Example>) Class.forName("Example");//输出:类初始化
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
类名.class是获取的类是静态解析方式;而后2种方式都是动态解析。
类名.class不进行类初始化,而Class.forName(类全名)会加载类并完成初始化。
4、public boolean equals(Object obj);
public boolean equals(Object obj) {
reurn this == obj;
}
5、public native int hashCode();
hashCode()方法返回一个整形数值,表示该对象的哈希码值。
两个对象相等 <=> equals()相等 => hashCode()相等
对象的hashCode()返回的不是对象所在的物理内存地址。甚至也不一定是对象的逻辑地址,hashCode()相同的两个对象,不一定相等,换言之,不相等的两个对象,hashCode()返回的哈希码可能相同。
6、public String toString();
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
顺带提一下,Class的getName()/getSimpleName()/getTypeName()区别在于:getName返回类全名;getSimpleName返回类名(不含包);getType与getName只是在返回集合类名时有差异。
7、wait(...)/notify()/notifyAll()
public final native void wait(long timeout) throws InterruptedException;
public final void wait() throws InterruptedException
public final void wait(long timeout, int nanos) throws InterruptedException
public final native void notify();
public final native void notifyAll();
wait():调用此方法所在的当前线程等待,直到在其他线程上调用此方法的主调(某一对象)的notify()/notifyAll()方法。
wait(long timeout)/wait(long timeout, int nanos):调用此方法所在的当前线程等待,直到在其他线程上调用此方法的主调(某一对象)的notisfy()/notisfyAll()方法,或超过指定的超时时间量。
notify()/notifyAll():唤醒在此对象监视器上等待的单个线程/所有线程。
8、protected void finalize();
只要对象中存在没有被适当清理的部分,程序就很隐晦的缺陷。finalize()可以用来最终发现这种情况。
class Book {
boolean checkedOut = false;
Book(boolean checkOut) {
checkedOut = checkOut;
}
void checkIn() {
checkedOut = false;
}
protected void finalize() throws Throwable {
if(checkedOut) {
System.out.println("Error: checked out");
}
super.finalize();
}
}
public class Test {
public static void main(String[] args) {
Book novel = new Book(true);
novel.checkIn();
new Book(true);
System.gc();
}
}
根搜索算法:这个算法的基本思路是通过一系列名为“GC roots”的对象作为起点,从这些节点开始向下搜索,搜索走过的路径称为引用连,当一个对象到GC roots没有任何引用链,则证明对象是不可用的。将被判定为可回收对象。不可达对象要被垃圾回收,至少要经历两次标记过程。第一次标记时执行finalize()方法,并做记号,第二次标记则不会再执行finalize()方法了。执行finalize()方法后,对象可能又变为可达对象,逃脱被垃圾回收的命运。参考链接:https://www.cnblogs.com/qiyu/p/3349667.html