面向对象
封装
private ----私有化
通过public–公共方法 获取和设置属性
高内聚低耦合
高内聚:类的内部数据操作细节自己完成,不允许外部干涉;
低耦合:仅对外暴露少量的方法用于使用。
★不对外暴露的私有的方法、单例模式
This
- this可以用来修饰、调用:属性、方法、构造器
- this修饰属性和方法;
this理解为:当前对象或当前正在创建的对象 - this调用构造器
- 我们在类的构造器中,可以显式的使用"this(形参列表)"方式,调用本类中指定的其他构造器
- 构造器中不能通过"this(形参列表)“方式调用自己
- 如果一个类中有n个构造器,则最多有n-1构造器中使用了"this(形参列表)”
- 规定:"this(形参列表)"必须声明在当前构造器的首行
- 构造器内部,最多只能声明一个"this(形参列表)"",用来调用其他的构造器
Package关键字
- 为了更好的实现项目中类的管理,提供包的概念
- 使用package声明类或接口所再的包,声明在源文件的首行
- 包,属于标识符,遵循标识符的命名规则、规范(xxxYYyzzz)、“见名知意”
- 每"."一次。就代表一层文件目录。
import关键字
import:导入
- 在源文件中显式的使用import结构导入指定包下的类、接口
- 声明在包的声明和类的声明之间
- 如果需要导入多个结构,则并列写出即可
- 可以使用"XXX.*"的方式,表示可以导入XXX包下的所有结构
- 如果使用的类或接口是java.lang包下定义的,则可以省略import结构
- 如果使用的类或接口是本包下定义的,则可以省略import结构
- 如果在源文件中,使用了不同包下的同名的类,则必须至少有一个类需要以全类名的方式显示。
继承
继承性的好处:
- 减少了代码的冗余,提高了代码的复用性
- 便于功能的扩展
- 为之后多态性的使用,提供了前提
继承中成员方法的访问特点
-
子类会继承父类的属性及方法
-
在主函数调用子类的内容的时候会按照 子类>父类的顺序 即先在子类找,没有就去父类找,都没有的话就会报错
public class fu{ public fu(){} //构造方法 } public class zi extends fu{ //继承的格式 public zi(){ super();//默认的 } }
继承中构造方法的访问特点
this.变量名-- 访问本类中的成员变量
super.变量名–访问的是父类中的成员变量
- 子类中所有的构造方法默认都会访问父类中无参的构造方法为什么呢?
-
因为子类会继承父类中的数据,可能还会使用父类的数据。所以子类初始化之前,一定要先完成父类数据的初始化
-
每一个子类构造方法的第一条语句默认都是:super()
- 如果父类中没有无参构造方法。只有带参构造方法。该怎么办呢?
- 通过使用super关键字去显示的调用父类的带参构造方法 即 添加一个带参的super(参数);
- 在父类中自己提供一个无参构造方法 ----推荐!!!
方法重写
-
子类类中出现了和父类中一模一样的方法声明
方法重写的应用
- 当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,既沿袭了父类的功能,又定义了子类特有的内容。
-
父类的私有方法 子类是无法重写的,即private修饰的方法
private和public 是访问权限修饰符
public > private
-
子类方法访问权限不能更低(public > 默认 > private)
继承的注意事项
- java中的类只支持单继承,不支持多继承 ,即一个类只能有一个父类
- java中的类支持多层继承,即 son继承father,father继承grandfather,相当于son继承grandfather、
- 子类直接继承的父类,称为,直接父类。间接继承的父类称为:间接父类
- 子类继承父类以后。就获取了直接父类以及所有间接父类中声明的属性和方法
- 如果我们没有显式的声明一个类的父类的话,则此类继承于java.lang.object类
- 所有的java类(除java.lang.object类之外)都直接或间接的继承于java.lang.object类
权限修饰符
private < 缺省(default)(默认) < protected < public
4种权限可以用来修饰类及类的内部结构:属性、方法、构造器、内部类
修饰类的话,只能使用:缺省、public
状态修饰符
final
★关键字是最终的意思,可以修饰成员方法,成员变量,类
特点:
- 修饰方法:表明该方法是最终方法,不能被重写
- 修饰变量:表明该变量是常量,不能再次被赋值 即C++里面的const
- 修饰类:表明该类是最终类,不能被继承
★final修饰局部变量
- 变量是基本类型: final修饰指的是基本类型的数据值不能发生改变
- 变量是引用类型: final修饰指的是引用类型的地址值不能发生改变,但是地址里面的内容是可以发生改变的
static
关键字是静态的意思,可以修饰或员方法,成员变量
类的成员如果是静态的,则通过类名可以直接调用(不需要创建对象)。比如Math.round(float a)
★static修饰的特点
- 被类的所有对象共享
这也是我们判断是否使用静态关健字的条件 - 可以通过类名调用
当然,也可以通过对象名调用
★static访问特点
非静态的成员方法
- 能访问静态的成员变量
- 能访问非静态的成员变量
- 能访问静态的成员方法
- 能访问非静态的成员方法
静态的成员方法
- 能访问静态的成员变量
- 能访问静态的成员方法
- 总结成一句话就是:静态成员方法只能访问静态成员
解释: 静态变量(方法) 属于每个对象共有的,而非静态… 属于每个对象本身的 属性或者行为,又因为静态…在没有创建的对象的时候可以直接调用,那时候没有对象还不能调用对象的非静态变量或者方法,所以静态成员方法只能访问静态成员 。 如果其他对象修改了静态变量,之后的每个对象的调用的这个静态变量都是修改后的值。
static修饰同性的其他说明:
-
静态变量随着类的加载而加载。可以通过"类.静态变量“的方式进行调用
-
静态变量的加载要早于对象的创建。
-
由于类只会加载一次,则静态变量在内存中也只会存在一份,存在方法区的静态域中。
开发中,如何确定一个属性是否要声明为static的?
属性是可以被多个对象所共享的。不会随着对象的不同而不同的。
开发中,如何确定一个方法是否要声明为static的?
- 操怍静态属性的方法,通常设置为static的
- 工具类中的方法,习惯上声明为static的。比如:Math、Arrays、collections
类修饰符
-
public(访问控制符),将一个类声明为公共类,他可以被任何对象访问,一个程序的主类必须是公共类。
-
abstract,将一个类声明为抽象类,没有实现的方法,需要子类提供方法实现。
-
final,将一个类生命为最终(即非继承类),表示他不能被其他类继承。
-
不加修饰符的时候 即直接声明 class A{ }
在这种情况下,class前面没有加任何的访问修饰符,通常称为“默认访问模式”,在该模式下,这个类只能被同一个包中的类访问或引用,这一访问特性又称包访问性。
多态
解释:1. 同一个对象,在不同时刻表现出来的不同形态。 2.一个事物的多种形态。
对象的多态性:父类的引用指向子类的对象。
多态的使用前提
- 类的继承关系
- 方法的重写
多态中成员访问特点
成员变量:编译看左边,执行看左边 即看父类中的变量
成员方法:编译看左边(意思是只能调用父类中的成员方法),执行看右边(运行的时候是看子类中的重写方法)
不能使用子类的特有功能
为什么成员变量和成员方法的访问不一样呢?
因为成员方法有重写,而成员变量没有
虚拟方法调用(多态情况下)
子类中定义了与父类同名同参数的方法,在多态情况下,将此时父类的方法称为虚拟方法,父类根据赋给它的不同子类对象,动态调用属于子类的该方法。这样的方法调用在编译期是无法确定的。即运行时行为(方法的调用是在运行时确定的)
instanceof关键字
a instanceof A --判断对象a是否是类A的实例。如果是返回true,否则返回false。
多态的好处和弊端
- 多态的好处: 提高了程序的扩展性
具体体现: 定义方法的时候,使用父类型作为参数,将来在使用的时候,使用具体的子类型参与操作 - 多态的弊端: 不能使用子类的特有功能
方法的重载与重写的区别
- 所以:对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法,这称为“早绑定”或“静态绑定”﹔
- 而对于多态,只有等到方法调用的那一刻,编译器才会确定所要调用的具体方法,这称为“晚绑定”或“动态绑定”。
- 引用一句Bruce Eckel的话:“不要犯傻,如果它不是晚绑定,它就不是多态。”
抽象类
abstract class
应用:抽象类是用来模型化那些父类无法确定全部实现,而是由其子类提供具体实现的对象的类。
特点
- 抽象类和抽象方法必须使用abstract关键字修饰
public abstract class 类名{}
public abstract void eat();
- 抽象类中不一定有抽象方法。有抽象方法的类一定是抽象类
- 抽象类不能实例化
抽象类如何实例化呢? 参照多态的方式,通过子类对象实例化,这叫叫抽象类多态 - 抽象类的子类
- 要么重写抽象类中的所有抽象方法
- 要么是抽象类
成员特点
-
成员变量
可以是变量也可以是常量 -
构造方法
有构造方法,但是不能实例化
那么,构造方法的作用是什么呢?用于子类访问父类数据的初始台化 -
成员方法
可以有抽象方法:限定子类必须完成某些动作
也可以有非抽象方法,提高代码复用性
- abstract不能用来修饰。属性、构造器等结构
- abstract不能用来修饰私有方法、静态方法、final的方法、final的类
接口
特点
- 接口用关键字interface修饰
public interface 接口名{} - 类实现接口用implements表示
public class 类名 implements 接口名{} - 接口不能实例化
接口如何实例化呢? 参照多态的方式,通过实现类对象实例化,这叫接口多态。 多态的形式: 具体类多态,抽象类多态,接口多态
多态的前提: 有继承或者实现关系; 有方法重写; 有父(类/接口)引用指向(子/实现)类对象 - 接口的实现类
要么重写接口中的所有抽象方法 要么是抽象类
成员特点
-
成员变量
只能是常量(或者一个确定的对象)
默认修饰符: public static final -
构造方法
接口没有构造方法,因为接口主要是对行为进行抽象的,是没有具体存在一个类如果没有父类,默认继承自Object类(只有一个空的构造方法) -
成员方法
只能是抽象方法
默认修饰符: public abstract -
类和接口的关系
实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
-
接口和接口的关系
继承关系,可以单继承,也可以多继承
JDK8以后 除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法
抽象类和接口的区别
-
成员区别
抽象类 变量,常量;有构造方法;有抽象方法,也有非抽象方法
接口 常量;抽象方法
-
关系区别
类与类 继承,单继承
类与接口 实现,可以单实现,也可以多实现
接口与接口 继承,单继承,多继承
-
设计理念区别
抽象类 对类抽象,包括属性、行为
接口 对行为抽象,主要是行为
抽象类名作为形参和返回值
- 方法的形参是抽象类名,其实需要的是该抽象类的子类对象
- 方法的返回值是抽象类名,其实返回的是该抽象类的子类对象
接口名作为 形参和返回值
- 方法的形参是接口名,其实需要的是该接口的实现类对象
- 方法的返回值是接口名,其实返回的是该接口的实现类对象
内部类
就是在一个类中定义一个类。举例:在一个类A的内部定义一个类B,类B就被称为内部类。
访问特点
- 内部类可以直接访问外部类的成员,包括私有
- 外部类要访问内部类的成员,必须创建对象
成员内部类
- 在类的成员位置:成员内部类
- 在类的局部位置:局部内部类
- 成员内部类,外界如何创建对象使用呢?
格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;
局部内部类
局部内部类是在方法中定义的类,所以外界是无法直接使用,需要在方法内部创建对象并使用该类可以直接访问外部类的成员,也可以访问方法内的局部变量
单例设计模式
解释:所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例。**优点:**由于单例模式只生成一个实例,减少了系统性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决。
//饿汉式
class Bank{
//1.私有化类的构造器
private Bank(){
}
//2.内部创建类的对象
//4.要求此对象也必须声明为静态的
private static Bank instance = new Bank();
//3.提供公共的方法,返回类的对象
public static Bank getInstance(){
return instance;
}
}
//懒汉式
class Order{
//1.私有化类的构造器
private Order(){
}
//2.声明当前类对象,没有初始化
//4.此对象也必须声明为static
private static Order instance = null;
//3.声明public、static的返回当前类对象的方法
public static Order getInstance(){
if(instance == null){
instance = new Order();
}
return instance;
}
}
区分饿汉式和懒汉式
饿汉式:
- 坏处:对象加载时间过长。
- 好处: 饿汉式是线程安全的
懒汉式:
- 好处:延迟对象的创建。
- 坏处:上面写的懒汉式代码----线程是不安全的 (利用多线程 可修复)
代码块
-
代码块的作用: 用来初始化类、对象
-
代码块如果有修饰的话,只能使用static
-
分类: 静态代码块vs非静态代码块
静态代码块:- 内部可以有输出语句
- 随着类的加载而执行, 而且只执行一次
- 如果一个类中定义了多个静态代码块,则按照声明的先后顺序执行
- 静态代码块的执行要优先于非静态代码块的执行
- 静态代码块内只能调用静态的属性、静态的方法,不能调用非静态的结构
非静态代码块:
- 内部可以有输出语句
- 随着对象的创建而执行
- 作用:可以在创建对象时,对对象的属性等进行初始化
- 如果一个类中定义了多个非静态代码块,则按照声明的先后顶序执行
- 非静态代码块内可以调用静态的早性、静态的方法,或非静态的属性、非静态的方法
执行顺序:由父及子 静态先行
属性赋值的顺序
对属性可以赋值的位置
①默认初始化
②显示初始化 / ⑤在代码块中赋值
③构造器中初始化
④有了对象以后,可以通过"对象.属性"或"对象.方法"的方式,进行赋值
先后顺序:① - ②/⑤ - ③ - ④
异常处理(Exception)
一、异常体系结构
java.lang.Throwable
-
java. lang.Error: 一球不编写针对性的代码进行处理。
-
java.lang.Exception:可以进行异常的处理
l ------编译时异常(checked)
例如:IOException、FileNotFoundException、classNotFoundException
l ------运行时异常(unchecked或者RuntimeException)例如:空指针(NullPointerException)、ArrayIndexOutOfBoundsException、ClasscastException、NumberFormatException、InputMismatchException、ArithmeticException
JAVA异常处理的方式
抓抛模型
过程一: “抛”:程序在正常执行的过程中,一旦出现一场,就会在一场代码出生成一个对应异常类的对象,并将此对象抛出。 一旦抛出对象之后,其后的代码就不再执行。
关于异常对象的产生: ①系统自动生成的异常对象
②手动生成一个异常对象,并抛出(throw) 例如:throw new RuntimeException(“不能能输入附属”);
过程二: “抓”,可以理解为异常的处理方式: ① try-catch-finally ② throws + 异常类型
try-catch-finally的使用
try {
//可能出现异常的代码
} catch(异常类型1 变量名1){
//处理异常的方式1
}catch(异常类型2 变量名2){
//处理异常的方式2
}catch(异常类型3 变量名3){
//处理异常的方式引
}…
finally{ //可选的
//一定会执行的代码
//资源释放
}
说明:1. finally 是可选的. finally会在抛出异常之前输出代码块的语句
- 使用try将可能出现异常代码包装起来,在执行过程中,一旦出现异常,就会生成一个对应异常类的对象,根据此对象的类型,去catch中进行匹配
- 一旦try中的作常对象匹配到某一个catch时,就进入catch中进行异常的处理。一旦处理完成,就跳出该try-catch结构(在没有写finally的前提下)。 继续执行下面的语句
- catch中的异常类型如果没有子父类关系,则谁声明在上,谁声明在下无所谓。
catch中的异常类型如果满足子父类关系,则要求子类一定声明在父类的上面。否则,报错。 - 常用的异常对象处理的方式: 异常变量.getMessage()—返回类型是String 异常变量.printStackTrace()
- 在try结构中声明的变量,再出了try结构以后,就不能再被调用。
**总结:**1.使用try-catch-finally处理编译时异常,是得程序在编译时就不再报错,但是运行时仍可能报错。
相当于我们使用try-catch-finally将一个编译时可能出现的异常,延迟到运行时出现。
2.开发中,由于运行时异常比较常见,所以我们通常就不针对运行时异常编写try-catch-finally了。针对于编译时异常,我们说一定要考虑异常的处理。
throws + 异常类型
"throws +异常类型"写在方法的声明处。指明此方法执行时,可能会抛出的异常类型。
**注意:**一旦当方法体执行时,出现异常。仍会在异常代码处生成一个异常类的对象,此对象满足throws后异常类型时,就会被抛出。异常代码后续的代码,就不再执行!
开发中如何选择使用try-catch-finally 还是使用throws?
- 如果父类中被重写的方法没有throws方式处理异常,则子类重写的方法也不能使用throws,意味着如果子类重写的方法中有异常,必须使用try-catch-finally方式处理。
- 执行的方法a中,先后又调用了另外的几个方法,这几个方法是递进关系执行的。我们建议这几个方法使用throws的方式进行处理。而执行的方法a可以考虑使用try-catch-finally方式进行处理。
如何自定义异常类?
- 继承于现有的异常结构:RuntimeException 、Exception(需要处理)。
- 提供全局常量: serialversionUID
- 提供重载的构造器
总结
声明异常 - throws
抛出异常 - throw
捕获异常 - try-catch 捕获并处理异常