面向对象:将功能封装进对象,强调具备了功能的对象 。
面向对象的三大特征:封装,继承,多态 。
类和对象是面向对象的核心概念 。
类是对一类事物的描述,是抽象的,概念上的定义 。
对象是实际存在的该类事物的每个个体,因此也称为实例 。
万事万物皆对象 。
java类及类的成员
java代码是由多个不同功能的类构成的 。
类的构成:
属性:对应类中的成员变量
行为:对应类中的成员方法(类似于 C 语言中说的函数概念)
构造器:相当于创建实例的模板
代码块:
内部类:
类中变量的分类:成员变量与局部变量
在方法体外,类体内声明的变量称为成员变量
在方法体内部声明的变量称为局部变量。
成员变量
实例变量(没有static修饰)
类变量(有static修饰)
局部变量
形参(方法签名中定义的变量)
方法局部变量(在方法内定义)
代码块局部定义(在代码块内定义)
注意:二者在初始化值方面的异同
同:都有生命周期
异:局部变量除形参外,需显示初始化 。
成员变量:
成员变量定义在类中,在整个类中都可以被访问 。
成员变量分为类成员变量和实例成员变量,实例变量存在于对象所在的堆内存中 。
成员变量有默认初始化值 。
成员变量的权限修饰符可以根据需要,选择任意一个 。
局部变量:
局部变量只定义在局部范围内,如:方法内,代码块内等 。
局部变量存在于栈内存中 。
作用的范围结束,变量空间会自动释放 。
局部变量没有默认初始化值,每次必须显式初始化 。
局部变量声明时不指定权限修饰符 。
重载:
在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可 。与返回值类型无关,只看参数列表,且参数列表必须不同 。(参数个数或参数类型) 。调用时,根据方法参数列表的不同来区别 。
封装:
Java 中通过将数据声明为私有的(private),再提供公共的(public)方法: getXxx() 和 setXxx() 实现对该属性的操作,以实现下述目的:
隐藏一个类中不需要对外提供的实现细节;
使用者只能通过事先定制好的方法来访问数据,可以方便地加入控制逻辑,限制对属性的不合理操作;
便于修改,增强代码的可维护性;
四种权限修饰符:
public:可以被所有其他类所访问
protected:自身、子类及同一个包中类可以访问
default:同一包中的类可以访问,声明时没有加修饰符,认为是 friendly
private:只能被自己访问和修改
构造器:创建对象;给对象进行初始化 。
它具有与类相同的名称
它不声明返回值类型 。(与声明为 void 不同)
不能被static、final、synchronized、abstract、native 修饰,不能有 return 语句返回值
this 关键字:
它在方法内部使用,即这个方法所属对象的引用;它在构造器内部使用,表示该构造器正在初始化的对象 。
this 表示当前对象,可以调用类的属性、方法和构造器 。
使用 this() 必须放在构造器的首行!
使用 this 调用本类中其他的构造器,保证至少有一个构造器是不用 this 的 。
JavaBean :所谓 javaBean,是指符合如下标准的Java类 。
类是公共的
有一个无参的公共的构造器
有属性,且有对应的 get、set 方法
为什么要有继承?
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可 。
继承的出现提高了代码的复用性 。
继承的出现让类与类之间产生了关系,提供了多态的前提 。
不要仅为了获取其他类中某个功能而去继承 。
子类不能直接访问父类中私有的( private )的成员变量和方法 。
一个子类只能有一个父类,一个父类可以派生出多个子类 。
方法的重写:在子类中可以根据需要对从父类中继承来的方法进行改造,也称方法的重置、覆盖 。在程序执行时,子类的方法将覆盖父类的方法 。
重写方法必须和被重写方法具有相同的方法名称、参数列表和返回值类型 。
重写方法不能使用比被重写方法更严格的访问权限 。
重写和被重写的方法须同时为 static 的,或同时为非 static 的 。
子类方法抛出的异常不能大于父类被重写方法的异常 。
关键字super:
super 可用于访问父类中定义的属性、成员方法 。
super 可用于在子类构造方法中调用父类的构造器 。
注意:
尤其当子父类出现同名成员时,可以用 super 进行区分 。
super 的追溯不仅限于直接父类 。
super 和 this 的用法相像,this 代表本类对象的引用,super 代表父类的内存空间的标识 。
子类中所有的构造器默认都会访问父类中空参数的构造器 。当父类中没有空参数的构造器时,子类的构造器必须通 this (参数列表)或者 super (参数列表)语句指定调用本类或者父类中相应的构造器,且必须放在构造器的第一行 。如果子类构造器中既未显式调用父类或本类的构造器,且父类中又没有无参的构造器,则编译出错 。
多态性,父类的引用指向了子类的实现 。是面向对象中最重要的概念,在java中有两种体现:
1 方法的重载( overload )和重写( overwrite ) 。
2 对象的多态性 ——可以直接应用在抽象类和接口上 。
Java 引用变量有两个类型:编译时类型和运行时类型 。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定 。若编译时类型和运行时类型不一致,就出现多态(Polymorphism)。
一个变量只能有一种确定的数据类型 。
一个引用类型变量可能指向(引用)多种不同类型的对象 。
一个引用类型变量如果声明为父类的类型,但实际引用的是子类对象,那么该变量就不能再访问子类中添加的属性和方法 。属性是在编译时确定的,此时父类中并没有相应的属性 。
多态性的前提:
需要存在继承或者实现关系
要有覆盖操作
成员方法:
编译时:要查看引用变量所属的类中是否有所调用的方法 。
运行时:调用实际对象所属的类中的重写方法 。
成员变量:
不具备多态性,只看引用变量所属的类 。
虚拟方法调用:只有在多态的情况下才会出现这种情况 。即父类的引用指向子类的对象,方法的调用是在运行时确定的,执行的是子类的方法 。
子类继承父类
若子类重写了父类方法,就意味着子类里定义的方法彻底覆盖了父类里的同名方法,系统将不可能把父类里的方法转移到子类中 。对于实例变量则不存在这样的现象,即使子类里定义了与父类完全相同的实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量 。
==操作符与 equals( ) 方法的比较:
==:
基本类型比较值 : 只要两个变量的值相等,即为 true 。
引用类型比较引用(是否指向同一个对象) : 只有指向同一个对象时,== 才返回 true 。
equals():所有类都继承了Object,也就获得了equals()方法 。还可以重写 。
只能比较引用类型,其作用与“==”相同 , 比较是否指向同一个对象 。但是一般我们会重写 equals 方法,使其比较类型及内容而不考虑引用是否相同 。比方说常见的 File、String、Date、及包装类,都已经重写了 equals 方法 。
拆箱:调用包装类的 xxxValue(); 方法 。
字符串转换成基本数据类型
通过包装类的构造器实现:int i = new Integer(“12”);
通过包装类的 parseXxx(String s) 静态方法:Float f = Float.parseFloat(“12.1”);
基本数据类型转换成字符串
调用字符串重载的 valueOf() 方法:String fstr = String.valueOf(2.34f);
更直接的方式:String intStr = 5 + “”
关键字 static:在 Java 类中,可用 static 修饰属性、方法、代码块、内部类 。
被修饰后的成员具备以下特点:
随着类的加载而加载
优先于对象存在(对象只有 new 了之后才存在)
修饰的成员,被所有对象所共享
访问权限允许时,可不创建对象,直接被类调用
在 static 方法内部只能访问类的 static 属性,不能访问类的非 static 属性 。
因为不需要实例就可以访问 static 方法,因此 static 方法内部不能有this 。(也不能有 super ? YES !)
重载的方法需要同时为 static 的或者非 static 的 。
设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式 。设计模式就像是经典的棋谱,不同的棋局,我们用不同的棋谱,免去我们自己再思考和摸索 。
所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法 。
1 我们首先必须将类的构造方法的访问权限设置为
private
2 调用该类的某个静态方法以返回类内部创建的对象,静态方法只能访问类中的静态成员变量,所以,指向类内部产生的该类对象的变量也必须定义成静态的 。
单例 ( Singleton ) 设计模式-饿汉式(不管三七二十一,上来就 new 一个对象)
class Single{
//private的构造器,不能在类的外部创建该类的对象
private Single() {}
//私有的,只能在类的内部访问
private static Single onlyone = new Single();
//getSingle()为static,不用创建对象即可访问
public static Single getSingle() {
return onlyone;
}
}
单例 ( Singleton ) 设计模式-懒汉式
class Singleton{
private Singleton(){
}
private static Singleton instance = null;
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
懒汉式存在线程安全问题,解决方法如下:
1 使用同步锁机制,最简单的是在 getInstance() 方法上加 synchronized 关键字
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance ;
}
2 双重判断实例,这种大大减少判断同步锁的次数了 。
public static Singleton getInstance() {
if (instance == null) {
// 同步代码块用的锁是单例的字节码文件对象,且只能用这个锁
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
3 当然最简单的方法就是使用饿汉式 。
初始化块 : 对 java 对象进行初始化
程序的执行顺序: 声明的成员变量的默认值——> 显示初始化,多个初始化块依次被执行——> 构造器再对成员进行赋值操作 。 所以,构造器是最后一道门 。
一个类中初始化块若有修饰符,则只能被 static 修饰,称为静态代码块( static block ),当类被载入时,类属性的声明和静态代码块先后顺序被执行,且只被执行一次 。static 块通常用于初始化 static (类)属性 。
关键字 final
final 修饰的类不能被继承
final 修饰的方法不能被子类重写
final 修饰的变量为常量
关键字 abstract
用abstract关键字来修饰一个类时,这个类叫做抽象类;
用abstract来修饰一个方法时,该方法叫做抽象方法。
抽象方法:只有方法的声明,没有方法的实现 。以分号结束:abstract int abstractMethod( int a );
含有抽象方法的类必须被声明为抽象类 。
抽象类不能被实例化 。
抽象类是用来被继承的,抽象类的子类必须重写父类的抽象方法,并提供方法体 。
若没有重写全部的抽象方法,仍为抽象类 。
不能用 abstract 修饰属性、私有方法、构造器、静态方法、final 的方法。
接口 ( interface ) 是抽象方法和常量值的定义的集合 。从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现 。
接口的特点:
用interface来定义 。
接口中的所有成员变量都默认是由 public static final 修饰的 。
接口中的所有方法都默认是由 public abstract 修饰的 。
接口没有构造器 。
接口采用多继承机制 。
实现接口的类中必须提供接口中所有方法的具体实现内容,方可实例化。否则,仍为抽象类 。
接口和抽象类的比较:
抽象类 接口
定义: 包含一个抽象方法的类 抽象方法和全局常量的集合
组成:构造方法,抽象方法,普通方法,常量 变量 常量 抽象方法
使用:子类继承抽象类 子类实现接口
关系:抽象类可以实现多个接口 接口不能继承抽象类,但允许继承多个接口
常见的设计模式:模板设计模式 工厂设计模式 代理设计模式
对象:都通过对象的多态性产生实例化对象
局限: 抽象类有单继承的局限 接口没有此局限
实际: 作为一个模板 是作为一个标准或表示一种能力
选择:如果都能用的话,选择接口,可以避免单继承的局限
在开发中,一个类不要去继承一个已经实现好的类,要么继承抽象类,要么实现接口
类的成员之五:内部类
在 Java 中,允许一个类的定义位于另一个类的内部,前者称为内部类,后者称为外部类 。Inner class 可以使用外部类的私有数据,因为它是外部类的成员,同一个类的成员之间可相互访问。而外部类要访问内部类中的成员需要:内部类.成员或者内部类对象.成员 。
分类:
成员内部类(static 成员内部类和非 static 成员内部类)
局部内部类(不谈修饰符)、匿名内部类
Inner class 作为类的成员:
可以声明为 final 的
和外部类不同,Inner class 可声明为 private 或 protected;
Inner class 可以声明为 static 的,但此时就不能再使用外层类的非 static 的成员变量;
Inner class作为类:
可以声明为 abstract 类 ,因此可以被其它的内部类继承
【注意】非 static 的内部类中的成员不能声明为 static 的,只有在外部类或 static 的内部类中才可声明 static 成员 。
匿名内部类
匿名内部类不能定义任何静态成员、方法和类,只能创建匿名内部类的一个实例 。一个匿名内部类一定是在 new 的后面,用其隐含实现一个接口或实现一个类 。
new 父类构造器(实参列表)|实现接口( ){
//匿名内部类的类体部分
}