1.面向对象的三个特征
封装:封装把对象的所有组成部分组合在一起,封装定义程序如何引用对象的数据,封装实际上使用方法将类的数据隐藏起来,控制用户对类的修改和访问数据的程度。
继承:继承实际上是存在与面向对象程序中的两个类之间的一种关系。当一个类拥有另一个类的所有数据和操作时,就称这两个类之间具有继承关系,private属性除外。
被继承的类称为父类或者超类,继承了父类的所有数据和操作的类称为子类。
使用继承的主要优点是:使程序结构清晰,减少编码,减少维护的工作量。
多态:定义:使用父类对象的地方都可以使用子类的对象,这就是所谓的多态。简单来说,多态意味着父类型的变量可以引用子类型的对象。
2.类的定义
[修饰符] calss 类名 [继承父类] [接口]
{
成员变量;
构造方法;
成员方法;
}
文件名必须与public类名相同。
3.创建对象
使用下列语法可创建对象:
new 构造函数
关键字new通常为创建运算符,用于分配对象内存,并将该内存初始化为缺省值。
一旦new完成分配和初始化内存,它就将调用构造函数来执行对象的初始化。
当创建一个类时,只是创建了一种新的数据类型,对象是类的一个实例。
4.构造函数
构造函数是类的一种特殊方法,主要表现:
1、构造函数的方法名与类名相同。
2、构造函数没有返回类型。
3、构造函数的主要工作是完成对类对象的初始化工作。
5.默认构造函数
默认构造函数指没有参数的构造函数。
如果编写的类没有构造函数,系统会自动提供一个默认构造函数,它把所有的属性设为默认值。
方法
方法是类的主要组成部分。在一个类中,程序的作用主要体现在方法中。方法是Java语言的基本构件,利用方法可以组成结构良好的程序。
方法的声明
一般的方法声明格式:
[访问控制符] [修饰符] 返回类型 方法名(参数表) [throws 异常类名表]{
... ...//方法体
}
方法的调用
方法是类的一个动态属性,先创建类的一个实例对象,通过 对象.方法名 来调用方法。
this关键字
this是指向调用对象本身的引用名。你可以在当前类的类型所允许对象的任何地方将this作为一个引用。
this实际上主要用于两个方面:
1、引用当前对象。
2、使得类的一个构造函数可以调用类的另一个构造函数。
包(package)
Java的文件名必须和public的类名相同,为了解决同名的冲突和类的访问权限的控制,Java提供包来管理类名空间。
package语句必须放在Java源文件的第一条语句,指明该文件中定义的类所在的包。
导入包import
为了能够使用Java API中已经提供的类或者我们自己写的类,需要import语句来导入所需要的类,这样能更好的解决命名空间的问题。
6.属性或方法的访问权限
当前类 | 同包 | 子类 | 其他 | |
public | √ | √ | √ | √ |
protected | √ | √ | √ | |
default | √ | √ | ||
private | √ |
类中限定为private的成员(属性或者方法),只能被这个类本身访问,即私有访问控制。
注意:不能够在方法体内声明的变量前加任何访问控制符,包括private。
protected
类中被限定为protected的成员变量和成员方法,可以被这个类本身以及它的子类访问(包括同一包和不同包中的子类都可以访问)。
public
类中被限定为public的成员,都是公共的,可以被所有的类访问,它的访问权限是最大的,但同时也是最不安全的,一般情况下成员变量都是定义成private。
7.非访问控制符
类,属性,方法可以拥有若干修饰符,包括访问控制符和非访问控制符。
static
final
8.static关键字
static修饰类的成员变量或者方法的时候,表明类的这些成员是属于整个类的,不属于任何一个一个类的具体的对象实例,它不保存在某个对象实例的内存区间中,而是保存在类的内存区域的公共存储单元。换句话说,对于该类的任何一个具体对象而言,静态域是一个公共的存储单元,任何一个对象访问它都是取得相同的数据;同样,任何一个对象去修改它,也都是对同一个内存单元进行修改。
声明为static的变量实质上就是全局变量。
不管创建了类的多少实例,整个类中静态变量的副本只有一个(static成员与对象无关)。
引用静态变量的方法
1、通过类的任一实例。
2、通过类的名称。
9.静态方法
类的静态方法只能访问其它的静态成员:静态变量和静态方法既可以在类的实例方法中使用,也可以在类的静态方法中使用。但是,实例变量和实例方法(即非静态成员)只能在实例方法中使用,不能在静态方法中使用,因为静态变量和静态方法不属于某个特定的对象。
静态方法不能被覆盖为费静态方法。
静态方法中也不能使用this和super。
10.final关键字
final变量实质上是一个常量。
final方法表明子类不能覆盖此方法。
final类不能够被继承。
11.final变量
一个变量可以声明为final,为了防止它的内容被修改。
声明final变量后,只能被初始化一次,然后就不能对其值进行修改。
一个final变量实质上是一个常量。
12.final变量的好处
效率:声明final字段有助于优化器做出更好的优化决定,因为如果编译器知道字段的值不会被更改,那么它能安全的在寄存器中高速缓存该值。
安全:使某部分状态不变可以大大简化开发,使得程序更加安全。
13.final方法
在方法声明中使用final关键字向编译器表明子类不能覆盖此方法,在子类中不能被重写。
14.final方法的好处
安全:将方法声明为final,那就说明你已经知道这个方法提供的功能已经满足你的需求,不需要进行拓展,并且也不允许任何从此类继承来的类重写这个方法,但是仍然可以继承这个方法,也就是说可以直接使用。
效率:有一种被称为inline机制,它会使你在调用final方法时,直接将方法主体插入到调用处,而不是进行例行的方法调用。
15.final类
声明为final的类不能被继承。
如果一个类为final类,那么它所有方法都为隐式的final方法。
16.final类的好处
效率:但是性能并不是将类或方法声明为final的好理由。
简化:不变类对于简化面向对象程序的设计非常有用,不变的对象只需要较少的防御性编码。
安全:防止类的属性和方法发生改变。
类中的常量
类中的常量是被该类的所有对象共享的,因此,常量应该声明为final static。例如:Math中的常量PI是这样定义的:final static double PI=3.14159265358979323846
并非所有的成员变量为private并且没有修改器方法的类就是不可变的。
要使一个类成为不可变的,它必须满足以下要求:
1、所有数据域都是私有的。
2、没有修改器方法。
3、没有一个访问器方法,它会返回一个指向可变数据域的引用。
17.单继承和多重继承
单重继承是指任何一个类都只有一个单一的父类;多重继承是指一个类可以有一个以上的父类。
支持多继承的程序,其结构为复杂的网状,能更自然地模拟现实世界,但设计、实现都比较复杂。
Java出于安全、可靠性的考虑,只支持单重继承。
子类从父类获得哪些能力?
子类继承父类的属性(变量),功能(方法),子类中只需声明特有的东西。
1、带private修饰符的属性、方法是不能被继承的。
2、带protected修饰符的属性、方法是被继承的。
3、构造方法不能被继承。但子类构造方法可以用super()或者super(parameters)方法调用父类的构造方法,而且super语句必须放在子类构造方法的第一行。
super指向该关键字所在类的父类。
Java的继承
[类修饰符] class <子类名> extends <父类名>
{
<域定义>;
<方法定义>;
}
在定义子类时用extend关键字指明新定义类的父类,就在两个类之间建立了继承关系。新定义的类称为子类,它可以从父类那里继承所有非private的域和方法作为自己的属性。
18.方法的重载
方法的重载是指一个类中可以定义有相同名字,但参数不同 的多个方法。调用时,会根据不同的参数表选择对应的方法。
构造函数的重载
构造函数也可以重载,要求使用不同的参数个数,不同的参数类型。构造函数的重载,可以让用户用不同的参数来构造不同的对象。
19.继承在开发中的作用
1、继承允许代码重用。
2、扩展新功能适应新情况
20.super的使用
1、使用super可以调用父类的构造方法:super(传参数给从父类继承而来的成员变量)
2、使用super来调用父类的成员方法:在子类中继承了父类中的成员方法,一般可以直接通过方法名使用,但是如果在子类中覆盖了父类的成员方法以后,如果需要在子类内部调用父类中被覆盖的成员方法时则不能直接调用了,这样就又需要使用super关键字了:super.父类方法(方法参数);
3、可使用super来引用父类的成员变量:在子类中如果引用从父类继承的成员变量,也可以使用“super.成员变量”来引用,只是一般成员变量的覆盖是没有意义的,所以这个时候都可以直接使用成员变量名进行引用,所以这里的super都可以省略。
21.调用父类的构造函数
子类可通过调用super()方法来调用超类(父类)的构造函数,对从父类继承而来的成员变量进行初始化。而且,super()必须放在子类构造函数中的第一行。
注意:this和super都是非静态的,所以这两个关键字都无法在静态方法内部进行使用。
22.父类对象与子类对象的转换
1、子类对象可以视作是一个父类的对象。如:Student对象也是一个People对象
2、父类对象不能被当做一个子类对象。
3、如果一个方法的形参是父类对象,调用这个方法时可以使用子类的对象作为实际参数。
4、如果父类对象指向的实际上确实是一个子类对象,那么这个父类对象可以用强制类型转换成子类对象的引用。
匹配一个方法签名与绑定方法实现是两个不同的问题:
方法匹配:根据参数的类型、个数、以及出现的顺序来匹配选择。
绑定方法的实现:由于一个方法可能被几个子类实现。所以JVM在运行时动态绑定方法的实现。
23.泛型编程
24.转换对象
从父类对象转换为子类对象时必须进行显式强制转换。而且未必成功。
25.垃圾回收
Java中的对象使用new进行创建,而由系统自动进行对象的清除,清除无用对象的过程,称为垃圾回收。
对象的回收是由Java虚拟机的垃圾回收线程来完成的,该线程对无用的的对象在适当的时机进行回收。
与C++等语言相比,其最大的特色之一就是:无用的对象由系统自动进行清除和内存的回收,程序员可以不用关心如何回收以及何时回收,大大减轻了工作的负担和回收对象带回来的潜在错误。
26.finalize()方法
finalize()方法类似于C++中的析构函数,当一个对象变成垃圾,它所引用的对象没有被别的有效句柄引用的话,finalize()方法将对象从内存中释放。
垃圾回收机制不由程序员控制,也无规律可循,并不会一产生了垃圾,它就被唤起,我们无法保证每个对象的finalize()方法最终都会被调用。
27.System.gc()方法
使用这个方法可以强制启动垃圾回收机制来回收垃圾,就像我们主动给环卫局打电话,通知他们提前来清扫垃圾的道理是一样的。
28.域的继承和隐藏
子类可以继承父类的所有非私有域。
子类重新定义一个父类那里继承来的域变量完全相同的变量,称为域的隐藏。
这里所谓的隐藏是指子类拥有了两个相同名字的变量,一个继承父类,另一个有自己定义。当子类执行继承自父类的方法时,处理的是继承自父类的变量,而当子类执行它自己定义的方法时,所操作的就是它自定义的变量,而把继承自父类的变量“隐藏”起来了。
29.方法的继承与重写
之前我们了解到,子类可以继承父类的非私有方法。
方法的重写,又叫覆盖,是指子类重定义从父类继承来的一个同名方法,此时子类将清除父类方法的影响。子类可以通过重新定义与父类同名的方法,实现自身的行为。
30.方法重写的注意点
子类在重新定义父类已有的方法时,应保持与父类完全相同的方法头声明,即保持与父类完全相同的方法名、返回类型和参数列表,否则就不是方法的重写,而是子类定义了自己与父类无关的方法,父类的方法仍然存在。
31.隐藏与重写的意义
方法的重写与域的隐藏的不同之处在于:子类隐藏父类的域只是使之不可见,父类的同名域在子类对象中仍然占有自己独立的内存空间;而子类方法对父类同名方法的覆盖将清除父类方法占用的内存空间,从而使父类方法在子类对象中不复存在。
域的隐藏和方法的重写的意义在于:通过隐藏域和重写方法可以把父类的状态和行为改为自身的状态和行为,对外统一名字和接口,又不失其继承性。
32.抽象类(abstract)
1、抽象方法必须用abstract来修饰,它只有原型没有方法体(花括号也没有)。
2、一个包含抽象方法的类必须声明为抽象类;抽象类的方法必须被子类重写所有的抽象方法后才能被实例化,否则这个子类海是一个抽象类。
3、抽象类必须用abstract关键字修饰。
4、抽象类不能被实例化,也就是不能用new关键字去产生对象。
5、抽象类的方法定义为protected,因为它只能被子类使用,创建一个具体子类的实例时,它的父类构造方法被调用以初始化父类中定义的数据域。
6、可以定义不包含抽象方法的抽象类,而且即使父类是具体的,其子类也是可以抽象的。
7、抽象类可以用作一种数据类型定义对象数组(可以用于得到具体子类的实例的引用)。
33.抽象类的定义
abstract class AbstractClass{
.....
}
34.abstract注意要点
abstract不能与final并列修饰用一个类。
abstract不能与private,static,final并列修饰同一方法。
abstract方法必须位于abstract类中。
abstract类中可以不包含abstract方法。
abstract类不能被实例化,但抽象类可以有构造函数。
35.抽象类的优点
抽象类是它的子类的所有公共属性的集合,提高程序开发和维护的效率,把这些各类的公共属性从他们各自的类的定义中抽取出来形成一个抽象类的组织方法,显然比把公共属性保留在具体类中的方法要方便的多。
36.接口(interface)
接口的概念
接口是一种与类相似的结构,只包含常量和抽象方法,可看作是一种特殊的抽象类。其目的是指明多个对象的公同行为。
如果抽象类的所有方法是抽象的,就可以用接口来实现。Java不支持多重继承,但是可以实现多个接口。
用接口实现比多重继承更强的功能。
37.定义接口
public interface MyInterface{
int id=1;
void run();
}
接口的变量都是常量,默认都是public static final
接口中的方法都是抽象方法,默认都是public abstract
Java当中允许省略接口中这些默认的修饰符。
38.接口的继承
接口也具有继承性,同样它也可以继承父类所有的属性和方法。与类的继承不同的是,一个接口可以继承多个父接口,它们之间用逗号隔开,子接口将继承父类接口的所有属性和方法。类不支持多重继承,接口可以有多重继承。
public interface A{ show() ;}
public interface B{ display() };
public interface C extends A,B{ run(); }
39.接口的实现
implement关键字去实现一个接口中的所有方法。
一个类可以在继承一个父类的同时,实现一个或者多个接口。
calss students extends Personimplements A{
public void show(){
System.out.println("show...");
}
}
40.接口的意义
让类不必受限于单一继承的关系,而可以灵活的同时继承一些共有特性,从而达到多重继承的目的。通过接口使得不同层次,甚至不相关的类可以具有相同的行为。
calss bird implements Runner,Flyer{
void run(){}
void fly(){}
}
41.接口的引用
接口可以作为一种引用类型来使用。任何实现该接口的类的实例都可以存储在该接口类型的变量中,通过这些引用类型的变量我们可以访问实现类所实现的接口中的方法,java运行的时候系统动态的确定该使用哪个类的方法。
把接口作为一种数据类型,我们可以不需要了解对象所对应的具体的类,而着重于它们的交互。
通过实现Serializable接口实现对象序列化。
接口的引用,示例:
interface walkable{
public void walk();
}
public class InterfaceRef implements walkable{
public void walk(){
System.out.println("Walking...");
}
public static void main(String[] args){
walkable w=new InterfaceRef();//引用一个实现类
w.walk();//调用实现类的方法
}
}
持续更新中。。。