Java基础第五部分
面向过程
一种较早的编程思想,顾名思义就是该思想是站着过程的角度思考问题,强调的就是功能行为,功能的执行过程,即先后顺序,而每一个功能我们都使用函数(类似于方法)把这些步骤一步一步实现。使用的时候依次调用函数就可以了。
面向对象
一种基于面向过程的新编程思想,顾名思义就是该思想是站在对象的角度思考问题,我们把多个功能合理放到不同对象里,强调的是具备某些功能的对象,具 备某种功能的实体,称为对象。面向对象最小的程序单元是:类。面向对象更加符合常规的思维方式,稳定性好,可重用性强,易于开发大型软件产品,有良好 的可维护性。在软件工程上,面向对象可以使工程更加模块化,实现更低的耦合和更高的内聚。面向对象的本质就是:以类的方式组织代码,以对象组织(封装) 数据。
类和对象的关系
类(模板):是对现实生活中事物的描述。
对象:就是这类事物,实实在在存在的个体。
封装
封装性就是尽可能的隐藏对象内部细节,对外形成一道边界,只保留有限的接口和方法与外界进行交互。封装的原则是使对象以外的部分不能随意的访问和操作 对象的内部属性,从而避免了外界对对象内部属性的破坏。
可以通过对类的成员设置一定的访问权限,实现类中成员的信息隐藏。四种访问权限如下:
- private:类中限定为private的成员,只能被这个类本身访问。如果一个类的构造方法声明为private,则其它类不能生成该类的一个实例。
- default:类中不加任何访问权限限定的成员属于缺省的(default)访问状态,可以被这个类本身和同一个包中的类所访问。
- protected:类中限定为protected的成员,可以被这个类本身、它的子类(包括同一个包中以及不同包中的子类)和同一个包中的所有其他的类访问。
- public:类中限定为public的成员,可以被所有的类访问。
继承
子类的对象拥有父类的全部属性与方法,称作子类对父类的继承。
- Java中父类可以拥有多个子类,但是子类只能继承一个父类,称为单继承。
- 继承实现了代码的复用。
- Java中所有的类都是通过直接或间接地继承java.lang.Object类得到的。
- 子类不能继承父类中访问权限为private的成员变量和方法。
- 子类可以重写父类的方法,即命名与父类同名的成员变量。
- Java中通过super来实现对父类成员的访问,super用来引用当前对象的父类。super 的使用有三种情况:
- 访问父类被隐藏的成员变量,如:super.variable;
- 调用父类中被重写的方法,如:super.Method([paramlist]),super()调用父类构造方法;
- 调用父类的构造函数,如:super([paramlist]);
- 哪个对象在调用this所在的函数,this就代表哪个对象;
- 子类构造函数中第一行会隐式的利用super调用父类的无参构造函数。
- this没有继承也可以使用。super只在继承下使用
多态
对象的多态性是指在父类中定义的属性或方法被子类继承之后,可以具有不同的数据类型或表现出不同的行为。这使得同一个属性或方法在父类及其各个子类中 具有不同的语义。例如:"几何图形"的"绘图"方法,"椭圆"和"多边形"都是"几何图"的子类,其"绘图"方法功能不同。
- Java的多态性体现在两个方面:由方法重载实现的静态多态性(编译时多态)和方法重写实现的动态多态性(运行时多态)。
- 编译时多态:在编译阶段,具体调用哪个被重载的方法,编译器会根据参数的不同来静态确定调用相应的方法。
- 运行时多态:由于子类继承了父类所有的属性(私有的除外),所以子类对象可以作为父类对象使用。程序中凡是使用父类对象的地方,都可以用子类对象来代替。一个对象可以通过引用子类的实例来调用子类的方法。
重写
- 子类对父类的方法进行重新编写。如果在子类中的方法与其父类有相同的的方法名、返回类型和参数表,我们说该方法被重写 (Overriding)。
- 如需父类中原有的方法,可使用super关键字,该关键字引用了当前类的父类。
- 子类函数的访问修饰权限不能低于父类的。
构造器
构造函数特点:
- 函数名与类名相同
- 不用定义返回值类型
- 不可以写return语句
- 作用:给对象进行初始化
- 多个构造函数是以重载的形式存在的
- 构造函数间调用,只能使用this进行互相调用,this函数不能用在一般函数间。
- 在构造代码块中,对象一建立就立即运行,而且优先于构造函数执行。构造代码块中定义的是不同对象具有共性的初始化内容。
static
被 static 修饰的成员属于类,不属于单个这个类的某个对象,被类中所有对象共享,可以并且建议通过类名调用。被static 声明的成员变量属于静态成员变量, 静态变量 存放在 Java 内存区域的方法区。
static 关键字主要有以下四种使用场景
- 修饰成员变量和成员方法
- 静态代码块
- 修饰类(只能修饰内部类)
- 静态导包(用来导入类中的静态资源,1.5之后的新特性)
调用格式:
- 类名.静态变量名
- 类名.静态方法名()
类的初始化
当new 一个对象时,如果存在继承关系,类中各部分初始化的顺序为:
静态(父)——静态(子)——动态(父)——构造方法(父)——动态(子)——构造方法(子)
public class Ape {
static int age3 = 17;
static {
System.out.println("祖先静态代码块执行了"+age3);
}
public Ape(){
System.out.println("祖先构造器执行了");
}
{
System.out.println("祖先构造代码块执行了");
}
}
public class Person extends Ape{
static int age=25;
static {
System.out.println("父类静态代码块执行了"+age);
}
public Person(){
System.out.println("父类构造器执行了");
}
{
System.out.println("父类构造代码块执行了");
}
}
public class Student extends Person {
static int age2 = 63;
static {
System.out.println("子类静态代码块执行了"+age2);
}
public Student(){
System.out.println("子类构造器执行了");
}
{
System.out.println("子类构造代码块执行了");
}
}
public class TestInit {
public static void main(String[] args) {
Student student = new Student();
}
}
final修饰的变量可以在定义时初始化,也可以在构造代码块中初始化。final和static修饰的变量可以在定义时初始化,也可以在静态代码块中初始化,静态代码块只初始化一次。
修饰符
抽象类
编写一个类时,会给该类定义一些方法,这些方法是用来描述功能和具体实现的方式,这些方法都有方法体
例如:一个图形类应该有周长的方法,但是不同的图形求周长方法不一样。分析事物,发现共性,就出现了向上抽取。
方法的声名相同,但是方法功能主体不同,这样就可以向上抽取,但只是抽取方法声名,但不抽取方法主体,称这个方法就是抽象方法
抽象函数类必须被abstract关键字修饰,被abstract关键字修饰的类就是抽象类。
- 抽象类不能被实例化,如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。
- 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
- 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。
- 构造方法,类方法(用static修饰的方法)不能声明为抽象方法。
- 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。
接口
Java接口(Interface),是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)
interface修饰的类是接口。
- 接口中的变量会被隐式地指定为public static final变量。
- 方法会被隐式地指定为public abstract方法且只能是public abstract方法。
- 如果一个非抽象类遵循了某个接口,就必须实现该接口中的所有方法。
- 允许一个类实现多个接口。
抽象类和接口的区别
- 抽象类是对一种事物的抽象,即对类抽象,而接口是不同类之间行为的抽象。
- 抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;
- 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;
- 接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
- 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
- 接口不能有构造方法,抽象类可以有。
异常
异常的分类
Error:是程序中无法处理的错误,表示运行应用程序中出现了严重的错误。此类错误一般表示代码运行时JVM出现问题。通常有Virtual MachineError(虚拟机 运行错误)、NoClassDefFoundError(类定义错误)等。比如说当jvm耗完可用内存时,将出现OutOfMemoryError。此类错误发生时,JVM将终止线程。非 代码性错误。因此,当此类错误发生时,应用不应该去处理此类错误。
Exception::程序本身可以捕获并且可以处理的异常。
运行时异常(不受检异常):RuntimeException类极其子类表示JVM在运行期间可能出现的错误。编译器不会检查此类异常,并且不要求处理异常,比如用空值对 象的引用(NullPointerException)、数组下标越界(ArrayIndexOutBoundException)。此类异常属于不可查异常,一般是由程序逻辑错误引起的,在程序 中可以选择捕获处理,也可以不处理。
非运行时异常(受检异常):Exception中除RuntimeException极其子类之外的异常。编译器会检查此类异常,如果程序中出现此类异常,比如说IOException, 必须对该异常进行处理,要么使用try-catch捕获,要么使用throws语句抛出,否则编译不通过。
异常的处理
-
抛出异常:throw,throws
-
捕获异常:try,catch,finally
throw
public class TestNewException { public static void main(String[] args) { int a = div(5,0); System.out.println("===================="); } private static int div(int i, int j) { if(j==0) throw new ArithmeticException("除数不能为0");//抛出具体问题,编译时不检测 return i/j; } }
声明抛出异常throws
运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常
public class TestThrows {
public static void main(String[] args) {
try {
readFile();
}catch (FileNotFoundException e){
System.out.println("找不到指定路径");
}
}
public static void readFile() throws FileNotFoundException {
InputStream is = new FileInputStream("E:/iodemo/ch01.txt");
}
}
try代码块
public class TestTry {
public static void main(String[] args) {
int a = 1;
//捕获异常
try {
//可能产生异常的代码
readFile();
} catch (FileNotFoundException e) {
//异常的处理逻辑,将异常记录日志,异常封装后显示
System.out.println("系统找不到指定的路径");
}catch (Exception e){
}catch (Throwable e){
//可捕获多个异常,最大的写在后面
}
System.out.println("============================");
System.out.println(show());
}
public static void readFile() throws FileNotFoundException {
InputStream is = new FileInputStream("E:/iodemo/ch01.txt");
}
public static int show() {
int result = 0;
try {
return result;
}finally{
System.out.println("finally模块被执行");
result = 1;
}
}
}
注意点:
-
可以catch多个异常,但是最大的要写在后面,否则前面的会覆盖后面的。
-
如果程序是从try代码块或者catch代码块中返回时,finally中的代码总会执行。而且finally语句在return语句执行之后return返回之前执行的。
-
如果try和catch的return是一个变量时且函数的是从其中一个返回时,后面finally中语句即使有对返回的变量进行赋值的操作时,也不会影响返回的值,这也
侧面 证明了finally语句在return语句执行之后执行的
文章部分来源:https://blog.csdn.net/java_cxrs/article/details/91661623