一、面向对象的特征java
面向对象的三个基本特征:封装、继承、多态编程
封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。数组
封装,也就是把客观事物封装成抽象的类,而且类能够把本身的数据和方法只让可信的类或者对象操做,对不可信的进行信息隐藏。缓存
面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可使用现有类的全部功能,并在无需从新编写原来的类的状况下对这些功能进行扩展。app
经过继承建立的新类称为“子类”或“派生类”。框架
被继承的类称为“基类”、“父类”或“超类”。编程语言
继承的过程,就是从通常到特殊的过程。ide
要实现继承,能够经过“继承”(Inheritance)和“组合”(Composition)来实现。模块化
在某些 OOP 语言中,一个子类能够继承多个基类。可是通常状况下,一个子类只能有一个基类,要实现多重继承,能够经过多级继承来实现。函数
继承概念的实现方式有三类:实现继承、接口继承和可视继承。
Ø 实现继承是指使用基类的属性和方法而无需额外编码的能力;
Ø 接口继承是指仅使用属性和方法的名称、可是子类必须提供实现的能力;
Ø 可视继承是指子窗体(类)使用基窗体(类)的外观和实现代码的能力。
在考虑使用继承时,有一点须要注意,那就是两个类之间的关系应该是“属于”关系。例如,Employee 是一我的,Manager 也是一我的,所以这两个类均可以继承 Person 类。可是 Leg 类却不能继承 Person 类,由于腿并非一我的。
抽象类仅定义将由子类建立的通常属性和方法,建立抽象类时,请使用关键字 Interface 而不是 Class。
OO开发范式大体为:划分对象→抽象类→将类组织成为层次化结构(继承和合成) →用类与实例进行设计和实现几个阶段。
多态性(polymorphisn)是容许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值以后,父对象就能够根据当前赋值给它的子对象的特性以不一样的方式运做。简单的说,就是一句话:容许将子类类型的指针赋值给父类类型的指针。
实现多态,有二种方式,覆盖,重载。
覆盖,是指子类从新定义父类的虚函数的作法。
重载,是指容许存在多个同名函数,而这些函数的参数表不一样(或许参数个数不一样,或许参数类型不一样,或许二者都不一样)。
其实,重载的概念并不属于“面向对象编程”,重载的实现是:编译器根据函数不一样的参数表,对同名函数的名称作修饰,而后这些同名函数就成了不一样的函数(至少对于编译器来讲是这样的)。如,有两个同名函数:function func(p:integer):integer;和function func(p:string):integer;。那么编译器作过修饰后的函数名称多是这样的:int_func、str_func。对于这两个函数的调用,在编译器间就已经肯定了,是静态的(记住:是静态)。也就是说,它们的地址在编译期就绑定了(早绑定),所以,重载和多态无关!真正和多态相关的是“覆盖”。当子类从新定义了父类的虚函数后,父类指针根据赋给它的不一样的子类指针,动态(记住:是动态!)的调用属于子类的该函数,这样的函数调用在编译期间是没法肯定的(调用的子类的虚函数的地址没法给出)。所以,这样的函数地址是在运行期绑定的(晚邦定)。结论就是:重载只是一种语言特性,与多态无关,与面向对象也无关!引用一句Bruce Eckel的话:“不要犯傻,若是它不是晚邦定,它就不是多态。”
那么,多态的做用是什么呢?
咱们知道,封装能够隐藏实现细节,使得代码模块化;继承能够扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另外一个目的——接口重用!多态的做用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。
泛化(Generalization)
图表 1 泛化
在上图中,空心的三角表示继承关系(类继承),在UML的术语中,这种关系被称为泛化(Generalization)。Person(人)是基类,Teacher(教师)、Student(学生)、Guest(来宾)是子类。
若在逻辑上B是A的“一种”,而且A的全部功能和属性对B而言都有意义,则容许B继承A的功能和属性。
例如,教师是人,Teacher 是Person的“一种”(a kind of )。那么类Teacher能够从类Person派生(继承)。
若是A是基类,B是A的派生类,那么B将继承A的数据和函数。
若是类A和类B绝不相关,不能够为了使B的功能更多些而让B继承A的功能和属性。
若在逻辑上B是A的“一种”(a kind of ),则容许B继承A的功能和属性。
聚合(组合)
图表 2 组合
若在逻辑上A是B的“一部分”(a part of),则不容许B从A派生,而是要用A和其它东西组合出B。
例如,眼(Eye)、鼻(Nose)、口(Mouth)、耳(Ear)是头(Head)的一部分,因此类Head应该由类Eye、Nose、Mouth、Ear组合而成,不是派生(继承)而成。
聚合的类型分为无、共享(聚合)、复合(组合)三类。
聚合(aggregation)
图表 3 共享
上面图中,有一个菱形(空心)表示聚合(aggregation)(聚合类型为共享),聚合的意义表示has-a关系。聚合是一种相对松散的关系,聚合类B不须要对被聚合的类A负责。
组合(composition)
图表 4 复合
这幅图与上面的惟一区别是菱形为实心的,它表明了一种更为坚固的关系——组合(composition)(聚合类型为复合)。组合表示的关系也是has-a,不过在这里,A的生命期受B控制。即A会随着B的建立而建立,随B的消亡而消亡。
依赖(Dependency)
图表 5 依赖
这里B与A的关系只是一种依赖(Dependency)关系,这种关系代表,若是类A被修改,那么类B会受到影响。
感谢:http://blog.csdn.net/cancan8538/article/details/8057095
二、final, finally, finalize 的区别
一、final修饰符(关键字)。被final修饰的类,就意味着不能再派生出新的子类,不能做为父类而被子类继承。所以一个类不能既被abstract声明,又被final声明。将变量或方法声明为final,能够保证他们在使用的过程当中不被修改。被声明为final的变量必须在声明时给出变量的初始值,而在之后的引用中只能读取。被final声明的方法也一样只能使用,不能重载。
【例】
public class finalTest{
final int a=6;//final成员变量不能被更改
final int b;//在声明final成员变量时没有赋值,称为空白final
public finalTest(){
b=8;//在构造方法中为空白final赋值
}
int do(final x){//设置final参数,不能够修改参数x的值
return x+1;
}
void doit(){
final int i = 7;//局部变量定义为final,不可改变i的值
}
}
二、finally是在异常处理时提供finally块来执行任何清除操做。无论有没有异常被抛出、捕获,finally块都会被执行。try块中的内容是在无异常时执行到结束。catch块中的内容,是在try块内容发生catch所声明的异常时,跳转到catch块中执行。finally块则是不管异常是否发生,都会执行finally块的内容,因此在代码逻辑中有须要不管发生什么都必须执行的代码,就能够放在finally块中。
三、finalize是方法名。java技术容许使用finalize()方法在垃圾收集器将对象从内存中清除出去以前作必要的清理工做。这个方法是由垃圾收集器在肯定这个对象没有被引用时对这个对象调用的。它是在object类中定义的,所以全部的类都继承了它。子类覆盖finalize()方法以整理系统资源或者被执行其余清理工做。finalize()方法是在垃圾收集器删除对象以前对这个对象调用的。
感谢:http://blog.csdn.net/cyl101816/article/details/67640843
三、Java的Integer和int有什么区别
Java是面向对象的编程语言,一切都是对象,可是为了编程的方便仍是引入了基本数据类型,为了可以将这些基本数据类型当成对象操做,Java为每个基本数据类型都引入了对应的包装类型(wrapper class),int的包装类就是Integer,从Java 5开始引入了自动装箱/拆箱机制,使得两者能够相互转换,对应以下:
原始类型:boolean,char,byte,short,int,long,float,double
包装类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double
顺便一提,Java中的基本数据类型只有以上8个,除了基本类型(primitive type),剩下的都是引用类型(reference type)。
因此最基本的一点区别是:Ingeter是int的包装类,int的初值为0,Ingeter的初值为null。除此以外还有区别,请看代码:
[java] view plain copy
为何i4和i5比是true,而i6和i7比是false呢?关键就是看valueOf()函数了,这个函数对于-128到127之间的数,会进行缓存, Integer i4 = 127时,会将127进行缓存,下次再写Integer i5 = 127时,就会直接从缓存中取,就不会new了。因此i4和i5比是true,而i6和i7比是false。
而对于后边的i5和i8,以及i9和i10,由于对象不同,因此为false。
以上的状况总结以下:
1,不管如何,Integer与new Integer不会相等。不会经历拆箱过程,new出来的对象存放在堆,而非new的Integer常量则在常量池(在方法区),他们的内存地址不同,因此为false。
2,两个都是非new出来的Integer,若是数在-128到127之间,则是true,不然为false。由于java在编译Integer i2 = 128的时候,被翻译成:Integer i2 = Integer.valueOf(128);而valueOf()函数会对-128到127之间的数进行缓存。
3,两个都是new出来的,都为false。仍是内存地址不同。
4,int和Integer(不管new否)比,都为true,由于会把Integer自动拆箱为int再去比。
感谢:http://blog.csdn.net/login_sonata/article/details/71001851
四、重载和重写的区别
重写(Override)
重写是子类对父类的容许访问的方法的实现过程进行从新编写, 返回值和形参都不能改变。即外壳不变,核心重写!
重写的好处在于子类能够根据须要,定义特定于本身的行为。 也就是说子类可以根据须要实现父类的方法。
重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。例如: 父类的一个方法申明了一个检查异常 IOException,可是在重写这个方法的时候不能抛出 Exception 异常,由于 Exception 是 IOException 的父类,只能抛出 IOException 的子类异常。
方法的重写规则
重载(Overload)
重载(overloading) 是在一个类里面,方法名字相同,而参数不一样。返回类型能够相同也能够不一样。
每一个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。
只能重载构造函数
重载规则
区别点 | 重载方法 | 重写方法 |
---|---|---|
参数列表 | 必须修改 | 必定不能修改 |
返回类型 | 能够修改 | 必定不能修改 |
异常 | 能够修改 | 能够减小或删除,必定不能抛出新的或者更广的异常 |
访问 | 能够修改 | 必定不能作更严格的限制(能够下降限制) |
总结
方法的重写(Overriding)和重载(Overloading)是java多态性的不一样表现,重写是父类与子类之间多态性的一种表现,重载是一类中多态性的一种表现。
五、抽象类和接口有什么区别
接口和抽象类都是继承树的上层,他们的共同点以下:
1) 都是上层的抽象层。
2) 都不能被实例化
3) 都能包含抽象的方法,这些抽象的方法用于描述类具有的功能,可是不比提供具体的实现。
他们的区别以下:
1) 在抽象类中能够写非抽象的方法,从而避免在子类中重复书写他们,这样能够提升代码的复用性,这是抽象类的优点;接口中只能有抽象的方法。
2) 一个类只能继承一个直接父类,这个父类能够是具体的类也但是抽象类;可是一个类能够实现多个接口。
Java语言中类的继承是单继承缘由是:当子类重写父类方法的时候,或者隐藏父类的成员变量以及静态方法的时候,JVM使用不一样的绑定规则。若是一个类有多个直接的父类,那么会使绑定规则变得更复杂。为了简化软件的体系结构和绑定机制,java语言禁止多继承。
接口能够多继承,是由于接口中只有抽象方法,没有静态方法和很是量的属性,只有接口的实现类才会重写接口中方法。所以一个类有多个接口也不会增长JVM的绑定机制和复杂度。
对于已经存在的继承树,能够方便的从类中抽象出新的接口,可是从类中抽象出新的抽象类就不那么容易了,所以接口更有利于软件系统的维护和重构。
图中若是Sparrow继承类Bird 类 ,Boyin继承Airplane类,Sparrow 和Boyin想使用一样的flay方法那么是没有办法实现的,由于类的继承是单继承。
https://pic3.zhimg.com/v2-1f71b697cfd213ce382a35ee73790730_r.jpg
若是Bird和Airplane是接口那么Boyin想使用一样的flay方法就很简单了。在写一个接口让Sparrow和Boyin实现这个接口就能够了以下图:
做者:每天向上
连接:https://www.zhihu.com/question/20149818/answer/142270191
来源:知乎
著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。
六、说说反射的用途及实现
反射(Reflection)是Java程序开发语言的特征之一。它容许运行中的Java程序获取自身的信息,而且能够操做类或对象的内部属性。Oracle官方对反射的解释是:
Reflection enables Java code to discover information about the fields,methods and constructors of loaded classes,and to use reflected fields, methods, and constructors to operate on their underlying conunterparts, within security restrictions.
The API accommodates applications that need access to either the public members of a target object (based on its runtime class) or the members declared by a give class. It also allows programs to suppress default reflective access control.
简而言之,经过反射,咱们能够在运行时得到程序或者程序集中每个类型的成员和成员的信息。
程序中通常的对象的类型都是在编译器就肯定下来的,而Java反射机制能够动态地建立对象并调用其属性,这样的对象的类型在编译器是未知的。因此咱们能够经过反射机制直接建立对象,即便这个对象的类型在编译期是未知的。
反射的核心是JVM在运行时才动态的加载类或者调用方法/访问属性,它不须要事先(写代码的时候或编译期)知道运行的对象是谁。
Java反射框架主要提供如下功能:
一、在运行时判断任意一个对象所属的类
二、在运行时构造任意一个类的对象
三、在运行时判断任意一个类所具备的成员变量和方法(经过反射甚至能够调用private方法)
四、在运行时调用任意一个对象的方法
反射的主要用途:
反射最重要的用途是开发各类通用的框架。
基本运用
一、获取Class对象
二、判断是否为某个类的实例
三、建立实例
四、获取方法
五、获取构造器信息
六、获取类的成员变量(字段)信息
七、调用方法
八、利用反射建立数组
感谢:http://www.sczyh30.com/posts/Java/java-reflection-1/#%E4%B8%80%E3%80%81%E5%9B%9E%E9%A1%BE%EF%BC%9A%E4%BB%80%E4%B9%88%E6%98%AF%E5%8F%8D%E5%B0%84%EF%BC%9F