一、面向对象
万物皆对象
类:是抽象概念,仅仅是模板,比如说“演员”、“总统”。类是构造对象的模板和蓝图,用于描述一种数据类型。
对象:是你能够看到摸到的具体实物。
拿小甜饼举例,将类想象成制作小甜饼的机器,而对象就是一个小甜饼。由类构造(construct)对象的过程称作为创建类的实例(instance)。
封装继承多态
1.封装性
封装性就是把对象的属性和服务结合成一个独立的相同单位,并尽可能隐蔽对象的内部细节,包含两个含义:
◇ 把对象的全部属性和全部服务结合在一起,形成一个不可分割的独立单位(即对象)。
◇ 信息隐蔽,即尽可能隐蔽对象的内部细节,对外形成一个边界〔或者说形成一道屏障〕,只保留有限的对外接口使之与外部发生联系。
封装的原则在软件上的反映是:要求使对象以外的部分不能随意存取对象的内部数据(属性),从而有效的避免了外部错误对它的"交叉感染",使软件错误能够局部化,大大减少查错和排错的难度。
2.继承性
特殊类的对象拥有其一般类的全部属性与服务,称作特殊类对一般类的继承。例如,轮船、客轮;人、大人。一个类可以是多个一般类的特殊类,它从多个一般类中继承了属性与服务,这称为多继承。例如,客轮是轮船和客运工具的特殊类。
3.多态性
对象的多态性是指在一般类中定义的属性或服务被特殊类继承之后,可以具有不同的数据类型或表现出不同的行为。这使得同一个属性或服务在一般类及其各个特殊类中具有不同的语义。例如:"几何图形"的"绘图"方法,"椭圆"和"多边形"都是"几何图"的子类,其"绘图"方法功能不同。
Java的三(四)种特性
封装、继承、多态、(抽象)
二、重载与重写
重载(Overloading)
重载发生在本类,方法名相同,参数列表不同,与返回值无关,只和方法名,参数列表,参数的类型有关.
重载(Overload):首先是位于一个类之中或者其子类中,具有相同的方法名,但是方法的参数不同,返回值类型可以相同也可以不同。
(1):方法名必须相同
(2):方法的参数列表一定不一样。
(3):访问修饰符和返回值类型可以相同也可以不同。
其实简单而言:重载就是对于不同的情况写不同的方法。 比如,同一个类中,写不同的构造函数用于初始化不同的参数。
public class Test1 {
public void out(){
System.out.println("参数"+null);
}
//参数数目不同
public void out(Integer n){
System.out.println("参数"+n.getClass().getName());
}
//参数类型不同
public void out(String string){
System.out.println("参数"+string.getClass().getName());
}
public void out(Integer n ,String string){
System.out.println("参数"+n.getClass().getName()+","+string.getClass().getName());
}
//参数顺序不同
public void out(String string,Integer n){
System.out.println("参数"+string.getClass().getName()+","+n.getClass().getName());
}
public static void main(String[] args) {
Test1 test1 = new Test1();
test1.out();
test1.out(1);
test1.out("string");
test1.out(1,"string");
test1.out("string",1);
}
}
重写
重写发生在父类子类之间,比如所有类都是继承与Object类的,Object类中本身就有equals,hashcode,toString方法等.在任意子类中定义了重名和同样的参数列表就构成方法重写.
重写(override):一般都是表示子类和父类之间的关系,其主要的特征是:方法名相同,参数相同,但是具体的实现不同。
重写的特征:
(1):方法名必须相同,返回值类型必须相同
(2):参数列表必须相同
(3):访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为public,那么在子类中重写该方法就不能声明为protected。
(4):子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为private和final的方法。
(5):构造方法不能被重写,
简单而言:就是具体的实现类对于父类的该方法实现不满意,需要自己在写一个满足于自己要求的方法。
class Test{
public void out(){
System.out.println("我是父类方法");
}
}
public class Test1 extends Test{
@Override
//方法签名完全一致
public void out() {
System.out.println("我是重写后的子类方法");
}
public static void main(String[] args) {
Test test = new Test();
test.out();
test = new Test1();
test.out();
}
}
三、抽象类与接口
抽象类
抽象类是用来捕捉子类的通用特性的 。它不能被实例化,只能被用作子类的超类。抽象类是被用来创建继承层级里子类的模板。以JDK中的GenericServlet为例:
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
// abstract method
abstract void service(ServletRequest req, ServletResponse res);
void init() {
// Its implementation
}
// other method related to Servlet
}
当HttpServlet类继承GenericServlet时,它提供了service方法的实现:
public class HttpServlet extends GenericServlet {
void service(ServletRequest req, ServletResponse res) {
// implementation
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
// Implementation
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
// Implementation
}
// some other methods related to HttpServlet
}
接口
接口是抽象方法的集合。如果一个类实现了某个接口,那么它就继承了这个接口的抽象方法。这就像契约模式,如果实现了这个接口,那么就必须确保使用这些方法。接口只是一种形式,接口自身不能做任何事情。以Externalizable接口为例:
public interface Externalizable extends Serializable {
void writeExternal(ObjectOutput out) throws IOException;
void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
}
当你实现这个接口时,你就需要实现上面的两个方法:
public class Employee implements Externalizable {
int employeeId;
String employeeName;
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
employeeId = in.readInt();
employeeName = (String) in.readObject();
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt(employeeId);
out.writeObject(employeeName);
}
}
抽象类与接口的对比
什么时候使用抽象类
- 如果你拥有一些方法并且想让它们中的一些有默认实现,那么使用抽象类吧。
- 如果你想实现多重继承,那么你必须使用接口。由于Java不支持多继承,子类不能够继承多个类,但可以实现多个接口。因此你就可以使用接口来解决它。
- 如果基本功能在不断改变,那么就需要使用抽象类。如果不断改变基本功能并且使用接口,那么就需要改变所有实现了该接口的类。
四、final,finalize,finally的区别
1.简单区别:
final用于声明属性,方法和类,分别表示属性不可交变,方法不可覆盖,类不可继承。
finally是异常处理语句结构的一部分,表示总是执行。
finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,供垃圾收集时的其他资源回收,例如关闭文件等。
2.中等区别:
虽然这个单词在Java中都存在,但是并没太多关联:
final:java中的关键字,修饰符。
A).如果一个类被声明为final,就意味着它不能再派生出新的子类,不能作为父类被继承。因此,一个类不能同时被声明为abstract抽象类的和final的类。
B).如果将变量或者方法声明为final,可以保证它们在使用中不被改变.
1)被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。
2)被声明final的方法只能使用,不能重载。
finally:java的一种异常处理机制。
finally是对Java异常处理模型的最佳补充。finally结构使代码总会执行,而不管无异常发生。使用finally可以维护对象的内部状态,并可以清理非内存资源。特别是在关闭数据库连接这方面,如果程序员把数据库连接的close()方法放到finally中,就会大大降低程序出错的几率。
finalize:Java中的一个方法名。
Java技术使用finalize()方法在垃圾收集器将对象从内存中清除出去前,做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没被引用时对这个对象调用的。它是在Object类中定义的,因此所的类都继承了它。子类覆盖finalize()方法以整理系统资源或者执行其他清理工作。finalize()方法是在垃圾收集器删除对象之前对这个对象调用的。
3.详细区别:
这是一道再经典不过的面试题了,我们在各个公司的面试题中几乎都能看到它的身影。final、finally和finalize虽然长得像孪生兄弟一样,但是它们的含义和用法却是大相径庭。
final关键字我们首先来说说final。它可以用于以下四个地方:
1).定义变量,包括静态的和非静态的。
2).定义方法的参数。
3).定义方法。
4).定义类
PS:finally与return的执行顺序
- 如果程序是从try代码块或者catch代码块中返回时,finally中的代码总会执行。而且finally语句在return语句执行之后return返回之前执行的。可以使用编译器的Debug功能查看详细过程。
- 当finally有返回值时,会直接返回。不会再去返回try或者catch中的返回值。
- 如果try和catch的return是一个变量时且函数的是从其中一个返回时,后面finally中语句即使有对返回的变量进行赋值的操作时,也不会影响返回的值。
五、String
equals和 ==
对复合数据类型用 = = 进行比较的时候,比较的是他们在内存中的存放地址,所以,除非是同
一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。对java基本数据类
型而言,= =比较的是对象的值,如果值相等返回true。equals是一个方法,在object类中方法体
为return(this==obj)。但在一些类库当中这个方法被覆盖掉了,String,Integer,Date在这些
类当中equals有其自身的实现,而不再是比较对象在内存中的存放地址了。对于复合数据类型之
间进行equals比较,在没有覆写equals方法的情况下,他们之间的比较还是基于他们在内存中的
存放地址的。“equal”不能用于基本数据类型。只能用于类变量。对于基本数据类型要用其包
装类。
String、StringBuffer和StringBuilder三者区别
1、首先是运行速度:StringBuilder > StringBuffer > String
Java中对String对象进行的操作实际上是一个不断创建新的对象并且将旧的对象回收的一个过程,所以执行速度很慢,而StringBuilder和StringBuffer的对象是变量,对变量进行操作就是直接对该对象进行更改,而不进行创建和回收的操作,所以速度要比String快很多
2、安全程度:StringBuilder是线程不安全的,而StringBuffer是线程安全的
参考其他人博客,StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。所以如果要进行的操作是多线程的,那么就要使用StringBuffer,但是在单线程的情况下,还是建议使用速度比较快的StringBuilder。
3、结论
-
String:适用于少量的字符串操作
-
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
-
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况(有缓冲,耗时,可做到安全)
4、测试代码
public static void main(String[] args) {
stringTest();
stringBufferTest();
stringBuilderTest();
}
private static void stringBuilderTest() {
long start = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100000; i++) {
sb.append((char)Math.floor(Math.random()*(90-65+1)+65));
}
long end = System.currentTimeMillis();
System.out.println("StringBuilder 对于100000个随机字符的测试时间为:" + (end-start));
}
private static void stringBufferTest() {
long start = System.currentTimeMillis();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 100000; i++) {
sb.append((char)Math.floor(Math.random()*(90-65+1)+65));
}
long end = System.currentTimeMillis();
System.out.println("StringBuffer 对于100000个随机字符的测试时间为:" + (end-start));
}
private static void stringTest() {
String s = null;
long start = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
s += (char)Math.floor(Math.random()*(90-65+1)+65);
}
long end = System.currentTimeMillis();
System.out.println("String 对于100000个随机字符的测试时间为:" + (end-start));
}
String能否被继承
不可以,因为String类有final修饰符,而final修饰的类是不能被继承的,实现细节不允许改变。
关于final修饰符,介绍如下:
根据程序上下文环境,Java关键字final有“这是无法改变的”或者“终态的”含义,它可以修饰非抽象类、非抽象类成员方法和变量。你可能出于两种理解而需要阻止改变:设计或效率。
- final类不能被继承,没有子类,final类中的方法默认是final的。
- final方法不能被子类的方法覆盖,但可以被继承。
- final成员变量表示常量,只能被赋值一次,赋值后值不再改变。
- final不能用于修饰构造方法。
注意:父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final类型的。
如果一个类不允许其子类覆盖某个方法,则可以把这个方法声明为final方法。
使用final方法的原因有二:
1、把方法锁定,防止任何继承类修改它的意义和实现。
2、高效。编译器在遇到调用final方法时候会转入内嵌机制,大大提高执行效率。
String a = new String(“hello”);创建了几个对象
String a = "hello"与String b = new String(“hello”)的区别
六、基本类型和包装类型有哪些
八种基本数据类型
byte
short
int
long
char
double
float
boolean
byte范围
-128~127