zoukankan      html  css  js  c++  java
  • 面向对象基础

    面向对象编程

    面向对象基础

    面向对象编程,是一种通过对象的方式,把现实世界映射到计算机模型的一种编程方法。
    抽象的是类(class)
    具体的是实例(instance)

    class和instance

    class是一种对象模版,它定义了如何创建实例,因此,class本身就是一种数据类型
    instance是对象实例,instance是根据class创建的实例,可以创建多个instance,每个instance类型相同,但各自属性可能不相同

    定义class

    一个class可以包含多个字段(field),字段用来描述一个类的特征.

    创建实例

    new操作符创建类的实例,创建了一个类型的实例,并通过变量a指向它,可以通过这个变量来操作实例。访问实例变量可以用变量.字段.

    方法

    可以用private修饰field,拒绝外部访问。
    需要使用方法(method)来让外部代码可以间接修改field
    一个类通过定义方法,就可以给外部代码暴露一些操作的接口,同时,内部自己保证逻辑一致性。
    调用方法的语法是实例变量.方法名(参数);

    定义方法

    修饰符 方法返回类型 方法名(方法参数列表) {
        若干方法语句;
        return 方法返回值;
    }
    

    内部方法是可以调用private方法

    this变量

    在方法内部,可以使用一个隐含的变量this,它始终指向当前实例,通过this.field就可以访问当前实例的字段

    方法参数

    方法可以包含0个或任意个参数。方法参数用于接收传递给方法的变量值。调用方法时,必须严格按照参数的定义一一传递.

    可变参数

    可变参数用类型...定义,可变参数相当于数组类型

    参数绑定

    调用方把参数传递给实例方法时,调用时传递的值会按参数位置一一绑定。
    基本类型参数的传递,是调用方值的复制。双方各自的后续修改,互不影响。
    引用类型参数的传递,调用方的变量,和接收方的参数变量,指向的是同一个对象。双方任意一方对这个对象的修改,都会影响对方

    构造方法

    创建实例的时候,实际上是通过构造方法来初始化实例的。调用构造方法,必须用new操作符。

    默认构造方法

    一个类没有定义构造方法,编译器会自动生成一个默认构造方法
    如果自定义了一个构造方法,那么,编译器就不再自动创建默认构造方法
    既要能使用带参数的构造方法,又想保留不带参数的构造方法,那么只能把两个构造方法都定义出来
    创建对象实例的时候,按照如下顺序进行初始化:
    先初始化字段
    执行构造方法的代码进行初始化
    一个构造方法可以调用其他构造方法,这样做的目的是便于代码复用。调用其他构造方法的语法是this(…)

    方法重载

    有一系列方法,它们的功能都是类似的,只有参数有所不同,那么,可以把这一组方法名做成同名方法

    继承

    Java使用extends关键字来实现继承
    子类自动获得了父类的所有字段,严禁定义与父类重名的字段
    Java只允许一个class继承自一个类,因此,一个类有且仅有一个父类。只有Object特殊,它没有父类。

    protected

    子类无法访问父类的private字段或者private方法
    protected关键字可以把字段和方法的访问权限控制在继承树内部,一个protected字段和方法可以被其子类,以及子类的子类所访问

    super

    super关键字表示父类(超类)
    子类引用父类的字段时,可以用super.fieldName
    Java中,任何class的构造方法,第一行语句必须是调用父类的构造方法
    如果没有明确地调用父类的构造方法,编译器会帮我们自动加一句super();
    如果父类没有默认的构造方法,子类就必须显式调用super()并给出参数以便让编译器定位到父类的一个合适的构造方法
    子类不会继承任何父类的构造方法

    阻止继承

    向上转型

    一个子类类型安全地变为父类类型的赋值,被称为向上转型(upcasting
    父类变量可以指向子类类型实例
    向上转型实际上是把一个子类型安全地变为更加抽象的父类型

    向下转型

    一个父类类型强制转型为子类类型,就是向下转型(downcasting
    不能把父类变为子类,因为子类功能比父类多,多的功能无法凭空变出来。
    向下转型很可能会失败。失败的时候,Java虚拟机会报ClassCastException
    instanceof实际上判断一个变量所指向的实例是否是指定类型,或者这个类型的子类。
    Java 14开始,判断instanceof后,可以直接转型为指定变量,避免再次强制转型。
    这里总结一下:

    • 父类强制转换子类
    Father f = new Father();
    Son s = (Son)f;//出错 ClassCastException
    

    父类实例转换成子类不行

    • “假”父类转换子类
    Father f = new Son();
    Son s = (Son)f;
    

    父类对象引用子类实例,再强制转换可以

    • 子类强制转父类
    Son s = new Son();
    Father f = (Father)s;
    

    父类变量可以指向子类实例

    区分继承和组合

    继承是is关系,组合是has关系。

    多态

    在继承关系中,子类如果定义了一个与父类方法签名完全相同的方法,被称为覆写(Override)。
    子类覆写了父类的方法

    public class Main {
        public static void main(String[] args) {
            Person p = new Student();
            p.run(); // 应该打印Person.run还是Student.run?
        }
    }
    
    class Person {
        public void run() {
            System.out.println("Person.run");
        }
    }
    
    class Student extends Person {
        @Override
        public void run() {
            System.out.println("Student.run");
        }
    }
    

    这里是执行 Student.run(),这里就是Person变量指向Student实例,实际调用的是实例里的方法。
    Java的实例方法调用是基于运行时的实际类型的动态调用,而非变量的声明类型。

    多态

    多态:针对某个类型的方法调用,其真正执行的方法取决于运行时期实际类型的方法。多态的特性:运行期才能动态决定调用的子类方法。
    多态具有一个非常强大的功能,就是允许添加更多类型的子类实现功能扩展,却不需要修改基于父类的代码。

    覆写Object方法

    所有的class最终都继承自Object,所以可以覆写Object中的方法。

    调用super

    在子类的覆写方法中,如果要调用父类的被覆写的方法,可以通过super来调用。

    final

    继承可以允许子类覆写父类的方法。如果一个父类不允许子类对它的某个方法进行覆写,可以把该方法标记为final。用final修饰的方法不能被Override
    如果一个类不希望任何其他类继承自它,那么可以把这个类本身标记为final
    final修饰的字段在初始化后不能被修改。

    抽象类

    把一个方法声明为abstract,表示它是一个抽象方法,本身没有实现任何方法语句。
    如果父类的方法本身不需要实现任何功能,仅仅是为了定义方法签名,目的是让子类去覆写它,那么,可以把父类的方法声明为抽象方法:

    class Person {
        public abstract void run();
    }
    

    Person类也无法被实例化。必须把Person类本身也声明为abstract,才能正确编译它

    抽象类

    存在抽象方法,那么那个类就需要申明抽象类。
    因为无法执行抽象方法,因此这个类也必须申明为抽象类
    使用abstract修饰的类就是抽象类。我们无法实例化一个抽象类
    抽象类可以强迫子类实现其定义的抽象方法,否则编译会报错

    面向抽象编程

    • 上层代码只定义规范
    • 不需要子类就可以实现业务逻辑
    • 具体的业务逻辑由不同的子类实现,调用者并不关心。

    接口

    在抽象类中,抽象方法本质上是定义接口规范:即规定高层类的接口,从而保证所有子类都有相同的接口实现
    如果一个抽象类没有字段,所有方法全部都是抽象方法
    可以把该抽象类改写为接口:interface
    使用interface可以声明一个接口,不允许有字段
    当一个具体的class去实现一个interface时,需要使用implements关键字
    一个类只能继承自另一个类,不能从多个类继承。
    一个类可以实现多个interface

    接口继承

    一个interface可以继承自另一个interface,使用extends
    公共逻辑适合放在abstract class中,具体逻辑放到各个子类,而接口层次代表抽象程度,使用的时候,实例化的对象永远只能是某个具体的子类,但总是通过接口去引用它,因为接口比抽象类更抽象,使用上转型

    default方法

    接口中,可以定义default方法。实现类可以不必覆写default方法

    静态字段和静态方法

    实例字段:在一个class中定义的字段,每个实例都有独立的字段,各个实例的同名字段互不影响。
    静态字段(static field):静态字段只有一个共享“空间”,所有实例都会共享该字段。
    静态字段并不属于实例,虽然实例可以访问静态字段,但是它们指向的其实都是类名 class的静态字段,所有实例共享一个静态字段.推荐用类名来访问静态字段类名.静态字段.

    静态方法

    static修饰的方法称为静态方法。调用静态方法则不需要实例变量,通过类名就可以调用.静态方法内部,无法访问this变量,也无法访问实例字段,它只能访问静态字段。

    接口的静态字段

    interface是可以有静态字段的,并且静态字段必须为final类型
    public static final,这里可以省略。

    Java定义了一种名字空间,称之为包:package.
    类名(比如Person)只是一个简写,真正的完整类名是包名.类名
    在定义class的时候,需要在第一行声明这个class属于哪个包。
    Java虚拟机执行的时候,JVM只看完整类名,因此,只要包名不同,类就不同。
    包没有父子关系。java.utiljava.util.zip是不同的包,两者没有任何继承关系。

    包作用域

    位于同一个包的类,可以访问包作用域的字段和方法,不用public、protected、private修饰的字段和方法就是包作用域

    import

    在一个class中引用其他class

    • 直接写出完整类名
    • import语句,在写import的时候,可以使用*,表示把这个包下面的所有class都导入进来
      • 默认自动import当前package的其他class
      • 默认自动import java.lang.*

    作用域

    public

    定义为publicclassinterface可以被其他任何类访问

    private

    定义为privatefield、method无法被其他类访问
    确切地说,private访问权限被限定在class的内部,而且与方法声明顺序无关
    Java支持嵌套类,如果一个类内部还定义了嵌套类,那么,嵌套类拥有访问private的权限

    protected

    protected作用于继承关系。定义为protected的字段和方法可以被子类访问,以及子类的子类

    package

    包作用域是指一个类允许访问同一个package的没有public、private修饰的class,以及没有public、protected、private修饰的字段和方法。

    局部变量

    局部变量作用域从变量声明处开始到对应的块结束。方法参数也是局部变量。

    final

    final修饰class可以阻止被继承
    final修饰method可以阻止被子类覆写
    final修饰field可以阻止被重新赋值

    内部类

    Inner Class

    如果一个类定义在另一个类的内部,这个类就是Inner Class
    Inner Class的实例不能单独存在,必须依附于一个Outer Class的实例,可以修改Outer Classprivate字段

    Anonymous Class

    还有一种定义Inner Class的方法,它不需要在Outer Class中明确地定义这个Class,而是在方法内部,通过匿名类(Anonymous Class)来定义。
    在方法内部实例化了一个Runnable, Runnable本身是接口,接口是不能实例化的,所以这里实际上是定义了一个实现了Runnable接口的匿名类,并且通过new实例化该匿名类,然后转型为Runnable。在定义匿名类的时候就必须实例化它.除了接口外,匿名类也完全可以继承自普通类。

    Static Nested Class

    使用static修饰,称为静态内部类(Static Nested Class)它不再依附于Outer的实例,而是一个完全独立的类,因此无法引用Outer.this.但它可以访问Outerprivate静态字段和静态方法。

    classpath和jar

    classpathJVM用到的一个环境变量,它用来指示JVM如何搜索class
    Java是编译型语言,源码文件是.java,而编译后的.class文件才是真正可以被JVM执行的字节码
    classpath就是一组目录的集合,它设置的搜索路径与操作系统相关
    IDE中运行Java程序,IDE自动传入的-cp参数是当前工程的bin目录和引入的jar
    JVM根本不依赖classpath加载核心库

    jar包

    可以把package组织的目录层级,以及各个目录下的所有文件(包括.class文件和其他文件)都打成一个jar文件
    jar包实际上就是一个zip格式的压缩文件,而jar包相当于目录
    要执行一个jar包的class,就可以把jar包放到classpath

    创建jar包

    制作了一个zip文件,把后缀从.zip改为.jar
    Java社区提供了大量的开源构建工具,例如Maven,可以非常方便地创建jar包。

    模块

    jar文件就是class文件的容器。从Java 9开始引入的模块,主要是为了解决“依赖”这个问题.原有的Java标准库已经由一个单一巨大的rt.jar分拆成了几十个模块,这些模块以.jmod扩展名标识,可以在$JAVA_HOME/jmods目录下找到它们.所有的模块都直接或间接地依赖java.base模块,只有java.base模块不依赖任何模块,它可以被看作是“根模块”

  • 相关阅读:
    在线自动创建springboot工程
    java线程自带队列的使用以及线程阻塞
    如何分析java内存泄漏问题
    java接口入参模板化,适用于企业化服务远程调度模板化的场景,接口入参实现高度可配置化
    打造springboot高性能服务器(spring reactor的使用)
    docker 5 docker-阿里云加速配置
    docker 4 docker的三要素
    docker 3 docker安装
    docker 2 docker介绍
    docker 1 为什么要使用docker
  • 原文地址:https://www.cnblogs.com/strategist-614/p/14394807.html
Copyright © 2011-2022 走看看