1. Java 重写(Override)与重载(Overload)
- 重写(Override)
- 重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!
- 重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。
- 要求两同两小一大原则, 方法名相同,参数类型相同,子类返回类型小于等于父类方法返回类型(即:子返回类型要是父返回类型的子类型或者不变), 子类抛出异常小于等于父类方法抛出异常, 子类访问权限大于等于父类方法访问权限。
- 重载(Overload)
- 重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。
- 每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。
最常用的地方就是构造器的重载。
重载规则:- 被重载的方法必须改变参数列表(参数个数或类型不一样);
- 被重载的方法可以改变返回类型;
- 被重载的方法可以改变访问修饰符;
- 被重载的方法可以声明新的或更广的检查异常;
- 方法能够在同一个类中或者在一个子类中被重载。
- 无法以返回值类型作为重载函数的区分标准。
2. 正则表达式
大写表示“非”,d表示digit数字。非数字就是\D, w表示word,非单词就是\W
3. 抽象类(abstract)和接口
抽象类
- 最好不要有private因为私有和抽象放在一起,子类如果想重写父类的私有方法根本继承不过来,也就无法重写
- 抽象类中可以有非抽象方法,甚至抽象类中可以都是非抽象的方法(但是后者没有啥意义)
- 抽象类中是可以定义静态方法的,但是不可以定义静态抽象方法
接口
- 接口允许定义成员,但必须是常量,因为定义的变量,在编译的时候都会默认加上public static final。(final修饰的属性必须赋初始值)
- 在接口中的方法,永远都被public abstract来修饰。
- 接口中定义的方法都需要有实现类来实现,如果实现类不能实现接口中的所有方法则实现类定义为抽象类。
- JDK1.8之后接口可以写默认方法:default void run(){ }但是默认方法只可以由实现类的对象调用。
- JDK1.8之后接口可以写静态方法,但是只能用接口名调用。
- JDK1.9之后接口可以有私有方法,私有方法只能被其他私有方法或者默认方法调用。
比较
- 抽象类中可以有静态方法,接口中也可以有。
- 抽象类和接口类无法实例化(忽略匿名内部类),任何编译器中直接使用new会报错。
- 抽象类可以有构造方法,接口中不能有构造方法。
- 接口与抽象的区别就在于抽象类可以提供某些方法的部分实现,而接口则不可以,这也大概是抽象类唯一的优点。
4. JVM
- JVM内存状况+垃圾回收
-
类加载器:
Java语言系统自带有三个类加载器:
- Bootstrap ClassLoader 最顶层的加载类,主要加载核心类库,%JRE_HOME%\lib下的rt.jar、resources.jar、charsets.jar和class等。另外需要注意的是可以通过启动jvm时指定-Xbootclasspath和路径来改变Bootstrap ClassLoader的加载目录。比如java -Xbootclasspath/a:path被指定的文件追加到默认的bootstrap路径中。我们可以打开我的电脑,在上面的目录下查看,看看这些jar包是不是存在于这个目录。
- Extention ClassLoader 扩展的类加载器,加载目录%JRE_HOME%\lib\ext目录下的jar包和class文件。还可以加载-D java.ext.dirs选项指定的目录。
- Application ClassLoader也称为SystemAppClass 加载当前应用的classpath的所有类。
一般对于我们java程序员来说,类的加载使用的是双亲委派模型,即当一个类需要加载时,会将类传给Application ClassLoader,但是Application ClassLoader并不会加载,不管它是否能加载,而是传给它的"父类" Extension ClassLoader,Extension ClassLoader同样不会加载,同样传给 Bootstrap ClassLoader(注意不是我们常说的那种父类,但是可以这样理解),这时Bootstrap ClassLoader会判断它是否能加载,能加载就直接加载了,不能加载就传给Extension ClassLoader,Extension ClassLoader同样的判断是否能加载,能加载就直接加载,不能加载就传给Application ClassLoader,然后Application ClassLoader也判断能否加载,如果还是不能加载应该就是报ClassNotFoundException了。这就是双亲委托模型的简单理解了。
对于上面的"父类"为什么要打引号,因为它们并不是真的像java中继承的关系,而是组合的关系,即在"子类"中存在一个成员变量指向"父类"的引用。
双亲委派有啥好处:
它使得类有了层次的划分。就拿java.lang.Object来说,你加载它经过一层层委托最终是由Bootstrap ClassLoader来加载的,也就是最终都是由Bootstrap ClassLoader去找<JAVA_HOME>\lib中rt.jar里面的java.lang.Object加载到JVM中。这样如果有不法分子自己造了个java.lang.Object,里面嵌了不好的代码,如果我们是按照双亲委派模型来实现的话,最终加载到JVM中的只会是我们rt.jar里面的东西,也就是这些核心的基础类代码得到了保护。因为这个机制使得系统中只会出现一个java.lang.Object,不会乱套了。你想想如果我们JVM里面有两个Object,那岂不是天下大乱了。
5.面向对象的特征有哪些方面
- 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。
- 继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类、基类);得到继承信息的类被称为子类(派生类),继承让变化中的软件系统有了一定的延续性。
- 封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。面向对象的本质就是将现实世界描绘成一系列完全自治、封闭的对象。我们在类中编写的方法就是对实现细节的一种封装;我们编写一个类就是对数据和数据操作的封装。可以说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程接口。
- 多态:父类引用指向子类对象。如果我们定义了一个指向子类的父类引用类型,那么它除了能够引用父类的共性外,还可以使用子类强大的功能。但是父类类型的引用可以调用父类中定义的所有属性和方法,对于只存在与子类中的方法和属性它就望尘莫及了。
6. hashCode()方法和equals()方法
作用:在Java里都是用来对比两个对象是否相等一致。
那么equals()既然已经能实现对比的功能了,为什么还要hashCode()呢?因为重写的equals()里一般比较的比较全面比较复杂,这样效率就比较低,而利用hashCode()进行对比,则只要生成一个hash值进行比较就可以了,效率很高。
那么hashCode()既然效率这么高为什么还要equals()呢? 因为hashCode()并不是完全可靠,有时候不同的对象他们生成的hashcode也会一样(生成hash值得公式可能存在的问题),所以hashCode()只能说是大部分时候可靠,并不是绝对可靠,
所以我们可以得出:
- equals()相等的两个对象他们的