初识–面向对象
一、什么是面向对象(OO)
在了解面向对象前,加入一个对比概率面向过程(简称po)
1、概念
-
**面向过程:**分析出解决问题的步骤,然后用函数依次实现这些步骤,依次调用解决问题。
-
**面向对象:**把构成问题事务分解成各个对象,建立对象的目的不是解决某一步骤而是描述某个事物解决整个问题的步骤中的行为。
用一个从家到学校的例子来对比了解它们之接的关系。
假设:我从家到学校,首先我从家里面出发,中间我经历了先做大巴,然后做高铁,然后做地铁,最后我到达了学校。
1、面向过程解决方法
- 执行从家里面出发的方法
- 执行做大巴的方法
- 执行做高铁的方法
- 执行做地铁的方法
- 执行到达学校的方法
以上就是将解决我从家到学校这个问题的过程,它被拆成一个个方法,通过一个个方法的执行来解决问题。
2、面向对象解决方法
- 先创建两个对象,“我”,“交通”
- 向两个对象中添加对应属性和方法。
- 向“我”的对象中添加”:从家里面出发“,”到达学校“的方法
- 向“交通”的对象中添加:“做大巴”,‘’做高铁“,”做地铁“的方法
- 然后通过对象.方法的方式执行。
从上面就可以看出,面向对象编程就是先抽象出对象,然后用对象执行方法的方式解决问题。
在这里我们主要先了解面向对象。因为面向对象是通过属性.方法来完成的,所以它用低耦合的特性,使系统更加灵活、更加易于维护,代码复用率也更高。
二、面向对象编程的特性
三大基本特性:封装,继承,多态
1、封装
它指的是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该类所提供的方法来实现对内部信息的操作和访问。
访问控制符
Java 提供了 3 个访问控制符:private、 protected 和 public ,代表 3 种不同的访问级别,再加上一个默认的访问控制级别(不使用任何访问控制符),共有 4 个访问控制级别。
- private(当前类访问权限):类中的一个的成员被 private 修饰,它只能在当前类的内部被访问;
- default(包访问权限):类中的一个成员或者一个外部类不使用任何访问控制符修饰,它能被当前包下其他类访问;
- protected(子类访问权限):类中的一个的成员被 protected 修饰,它既可以被当前包下的其他类访问,又可以被不同包的子类访问;
- public(公共访问权限):类中的一个成员或者一个外部类使用 public 修饰,它能被所有类访问。
private | default(默认) | protected | public | |
---|---|---|---|---|
同一个类中 | ✔ | ✔ | ✔ | ✔ |
同一个包中 | ✔ | ✔ | ✔ | |
子类中 | ✔ | ✔ | ||
全局范围内 | ✔ |
2、继承
- Java 使用 extends 作为继承的关键字,子类扩展了父类,获得父类的全部成员变量和方法。
- Java 只能单继承,只有一个直接父类,但可以有无限多个间接父类。当一个 Java 类并未显式指定直接父类时,默认继承
java.lang.Object
,因此java.lang.Object
是所有类的直接或间接父类。(Ctrl+H 可以查看类关系) - 继承是类与类之间的一种关系,此外还有依赖、组合、聚合等。
- 子类继承了父类,就会拥有父类的全部方法,而private私有属性及方法无法继承。
- 被final修饰的类,无法被继承(断子绝孙)。
class B {
public void show() {
System.out.println("B");
}
}
public class A extends B{
@Override
public void show() {
System.out.println("A"); //重写父类方法
}
}
super & this
-
super()调用父类的构造方法,必须在构造方法的第一个
-
super必须只能出现在子类的方法或构造方法中
-
**super()和this()**不能同时调用构造方法,因为this也必须写在第一行
super与this的区别:
super代表父类对象的引用,只能在继承条件下使用;this调用自身对象,没有继承也可以使用。
方法的重写
- 重写:子类的方法必须与父类方法必须一致,方法体不同。
- 重写是方法的重写,与属性无关
- 重写方法只与非静态方法有关,与静态方法无关(静态方法不能被重写)
重载(Overload)和重写(Override)区别:
- 重载指的是同一类中多个同名方法;
- 重写指的是子类和父类的同名方法。
3、多态
多态是同一个行为具有多个不同表现形式或形态的能力。
多态就是同一个接口,使用不同的实例而执行不同操作,如图所示:
- 即同一方法可以根据发送对象的不同而采用不同的行为方式(多态的意义)
- 一个对象的实际类型是确定的,但可以指向对象的引用可以有很多(一般指父类,有关系的类),比如父类的引用指向子类
多态存在的三个必要条件
- 继承
- 重写
- 父类引用指向子类对象:Parent p = new Child();
父类Person.java
public void test(){
System.out.println("我是父类");
}
public void one(){
System.out.println("不要重写我,我怕");
}
子类OldPerson.java
//重写父类
public void test(){
System.out.println("我是子类");
}
//子类独有
public void test2(){
System.out.println("我在赶,我在靠");
}
测试类
public static void main(String[] args) {
//子类可以调用自己的和继承父类的
OldPerson old = new OldPerson();
old.test();
//父类没有被重写的方法
old.one();
//父类的引用指向子类
Person p_old = new OldPerson();
p_old.test();
// p_old.test2(); 用父类去强行调用子类独有的方法会报错
}
总结:
- 对象能调用的方法,主要和对象的左边类型有关,和右边关系不大
- 当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
- 多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。
- 多态是方法的多态,没有属性的多态
不能重写,不能实现多态的情况:
-
static 方法属于类,它不属于实例
-
final常量
-
private方法;
static(静态)
- 静态变量可以直接用类名访问,也称类变量。
- 静态变量(或方法)对于类,所有对象(实例)所共享。
public class OldPerson{
private static int name;//静态的变量
private double age;//非静态的变量
public void a(){
System.out.println("非静态的方法");
}
public static void b(){
System.out.println("静态的方法");
}
public static void main(String[] args) {
//静态(static)类型的方法和属性可以直接调用
System.out.println(name);
b();
//非静态(static)类型的方法和属性要调用需要先实例化该类(new OldPerson)
OldPerson old = new OldPerson();
old.a();
System.out.println(old.age);
}
}
- static类型的方法和类,在加载类时一起被初始化,最早执行且只执行一次(第一次new)。
public class OldPerson{
public static void main(String[] args) {
OldPerson old = new OldPerson();
System.out.println("----------------------------");
//在实例化一次是为了看static静态代码块在类执行时,只执行一次
OldPerson old2 = new OldPerson();
}
//匿名代码块
{
System.out.println("匿名代码块");
}
//静态代码块,类加载直接执行,永久执行一次
static {
System.out.println("静态代码块");
}
//构造器
public OldPerson() {
System.out.println("构造方法");
}
}
结果截图:
abstract(抽象类)
概念和约束:
- abstract修饰的类就是抽象类,修饰的方法就是抽象方法。
- 抽象类中可以没有抽象方法,但有抽象方法的类一定要声明为抽象类。
- 抽象类不能使用new来创建对象,它是用来让子类继承的。
- 抽象方法只有方法的声明,没有实现,让其子类实现。
- 子类继承抽象类,必须实现抽象类的所有方法,否则该子类也要声明为抽象类。
抽象类
//抽象类
public abstract class Person {
//抽象方法
public abstract void test2();
//普通方法
public void test(){
System.out.println("我是普通人");
}
}
继承抽象类
public class OldPerson extends Person{
@Override
public void test2() {
System.out.println("抽象方法实现");
}
public static void main(String[] args) {
OldPerson old = new OldPerson();
old.test2();
}
}
interface(接口)
概念:
Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
接口与类的区别:
- 接口不能用于实例化对象。
- 接口没有构造方法。
- 接口中所有的方法必须是抽象方法。
- 接口不能包含成员变量,除了 static 和 final 变量。
- 接口不是被类继承了,而是要被类实现。
- 接口支持多继承。
接口特性
- 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。
- 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)。
- 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。
抽象类和接口的区别
- 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
- 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
- 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
- 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
Aa接口类
public interface Aa {
//public static final int MAX_MUN=5;
int MAX_MUN=5; //属性 一般不用
// public abstract void test(); 与下面一样,我们一般选择下面那种方式
//抽象方法--无参
void test();
//抽象方法--有参
void test2(int a);
}
Impl接口实现类
//接口可以实现多继承
public class Impl implements Aa,Bb{
@Override
public void test() {
System.out.println("接口方法实现");
}
@Override
public void test2(int a) {
System.out.println("接口方法实现");
}
}
内部类
- 内部类就是在一个类的内部再定义一个类,比如A类中定义了一个B类,那么B就是A的内部类,而A相对B来说就是外部类
1、成员内部类:可以操作外部类的私有属性及方法
public class Person {
private long number=7000000000L;
public void out(){
System.out.println("外部方法");
}
//内部类
public class Inner{
public void in(){
System.out.println("这是内部方法");
}
//获取外部内私有类
public void getNumber(){
System.out.println(number);
}
}
}
public class Application {
public static void main(String[] args) {
Person person = new Person();
//person.new 这里是引用名person.new
Person.Inner inner = person.new Inner();
inner.in();
inner.getNumber();
}
}
2、静态内部类:static修饰,不能访问外部类私有属性
这里不能获取到number是因为内部类,增加了static修饰符,所以Inner内部类在Person类存在时就一起存在了,这个时候private long number=7000000000L;还没有存在,如果要获取在number属性上也加上一个static就又可以获取到了。
3、局部内部类:外部类的方法里定义的类
public class Person {
public void method(){
class Inner{
public void in(){
System.out.println("//一个java类中可以有多个class类,但是只能有一个public class类");
}
}
}
}
4、匿名内部类:没有名字初始化类
public class Person {
public static void main(String[] args) {
// Apple apple = new Apple();一般情况
new Apple().methon();//匿名,就是没有名字初始化类,不用把实例保存到变量中去
}
}
class Apple{
public void methon(){
System.out.println("匿名");
}
}
异常
三种类型的异常:
- **检查性异常:**最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
- 运行时异常: 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
- 错误: 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
Exception 类的层次
所有的异常类是从 java.lang.Exception 类继承的子类。
Exception 类是 Throwable 类的子类。除了Exception类外,Throwable还有一个子类Error 。
Java 程序通常不捕获错误。错误一般发生在严重故障时,它们在Java程序处理的范畴之外。
Error 用来指示运行时环境发生的错误。
例如,JVM 内存溢出。一般地,程序不会从错误中恢复。
异常类有两个主要的子类:IOException 类和 RuntimeException 类。
try {
//可以会异常的代码
}catch (Exception e){
/*
* 这里是处理异常的区域,上面的异常可以在这里进行处理或者提示一句话
* 我们一般直接抛出最高层异常 Exception 避免一些小异常没有发现
* */
}finally {
//可以存在 也可以不存在
//作用是不管有没有异常都会走这里,一般用来关闭IO流。
}
- 抛出异常
- 捕获异常
- 异常处理关键字:try、catch、finally、throw、throws
到此就结束了,在此声明,此文,只作本人复习使用。如有侵权,请联系我,将妥善处理。
邮箱:94618916@qq.com