Java基础学习笔记——面向对象(下)

来源:互联网 发布:php getfilecontents 编辑:程序博客网 时间:2024/05/18 19:46

面向对象(下)

1. 包装类

  • 对应关系

这里写图片描述

  • 自动装箱

    • 把一个基本类型变量直接赋给对应的包装类变量,或者赋给Object变量(Object是所有类的父类,子类对象可以直接赋给父类变量)
  • 自动拆箱

    • 包装类对象直接赋给一个对应的基本类型变量
  • 字符串转换成基本数据类型

    • 通过包装类的构造器实现

      • int i = new Integer(“12”);
    • 通过包装类的parseXxx(String s)静态方法

      • Float f = Float.parseFloat(“12.1”);
  • 基本数据类型转换成字符串

    • 调用字符串重载的valueOf()方法

      • String fstr = String.valueOf(2.34f);
    • 调用类中的toString方法

      • String s = t.toString();
    • 更直接的方式

      • String intStr = 5 + “”
  • 比较

    • 虽然包装类型的变量是引用数据类型,但包装类的实例可以与数值类型的值进行比较,这种比较是直接取出包装类实例所包装的数据类进行比较的。

2. 处理对象

  • 打印对象和toString方法

    • Object类提供个toString()方法总是返回该对象实现类的“类名+\@+hashCode”值

    • 可以根据需要在用户自定义类型中重写toString()方法

  • ==和equals方法

    • = =

      • 基本类型比较值:只要两个变量的值相等,不一定要求数据类型严格相同,即为true

      • 引用类型比较引用(是否指向同一个对象):只有指向同一个对象时,==才返回true.

      • 用“==”进行比较时,符号两边的数据类型必须兼容(可自动转换的基本数据类型除外),否则编译出错;

    • equals()

      • 所有类都继承了Object,也就获得了equals()方法。还可以重写

      • 只能比较引用类型,其作用与“==”相同,比较是否指向同一个对象

      • 当用equals()方法进行比较时,对类File、String、Date及包装类(Wrapper
        Class)来说,是比较类型及内容而不考虑引用的是否是同一个对象;原因:在这些类中**重写了**Object类的equals()方法

    • 重写

引用块内容

3.类成员

  • 理解类成员

    • static关键字修饰的成员就是类成员

    • 类变量属于整个类,当系统第一次准备使用该类时,系统会为该类变量分配内存空间,类变量开始生效,直到该类被卸载,该类的类变量所占有的内存才被系统的垃圾回收机制回收

    • 当使用实例来访问类成员时,实际上依然是委托给该类来访问类成员,因此即使某个实例为null,它也可以访问它所属类的类成员

    • 因为不需要实例就可以访问static方法,因此static方法内部不能有this。(也不能有super
      ? YES!)

4. final修饰符

  • 概述

    • final修饰变量时,表示该变量一旦获得了初始值就不可被改变,final既可以修饰成员变量(包括类变量和实例变量),也可以修饰局部变量、形参。
  • final成员变量

    • final修饰的成员变量必须由程序员显式地指定初始值

    • 指定初始值的地方

      • 类变量

必须在静态初始化块中指定初始值或声明该类变量时指定初始值,而且只能在两个地方的其中之一指定。

  • 实例变量

必须在非静态初始化块、声明该实例变量或构造器中指定初始值,而且只能在三个地方的其中之一指定。

  • final局部变量

    • 系统不会对局部变量进行初始化,局部变量必须由程序员显式初始化,因此使用final修饰局部变量时,既可以在定义时指定默认值,也可以不指定默认值

    • 如果final修饰的局部变量在定义时没有指定默认值,则可以在后面代码中对该final变量赋初始值,但只能一次,不能重复赋值

    • 如果final修饰的局部变量在定义时已经指定默认值,则后面代码中不能再对该变量赋值

    • 不能对final修饰的形参赋值,因为形参在调用该方法时,由系统根据传入的参数来完成初始化,因此使用final修饰的形参不能被赋值。

  • final修饰基本类型变量和引用类型变量的区别

    • 当使用final修饰基本类型变量时,不能对基本类型变量重新赋值,因此基本类型变量不能被改变

    • 对于引用类型而言,它保存的仅仅是一个引用,final只保证这个引用类型变量所引用的地址不会改变,即一直引用同一个对象,但这个对象完全可以发生改变。

  • 可执行“宏替换”的final变量

    • 满足条件

      • 使用final修饰符修饰

      • 在定义该final变量时指定了初始值

      • 该初始值可以在编译时就被确定下来

    • 对于final实例变量而言,只有在定义该变量时指定初始化值才会有“宏变量”的效果。

  • final方法

    • final修饰的方法不可被重写

    • 即使使用final修饰一个private访问权限的方法,依然可以在其子类中定义与该方法具有相同方法名、相同形参列表、相同返回值类型的方法。

  • final类

    • final修饰的类不可以有子类。
  • 不可变类

    • 设计一个不可变类,尤其要注意其引用类型的成员变量,如果引用类型成员变量的类是可变的,就必须采用必要的措施来保护该成员变量所引用的对象不会被修改,这样才能创建真正的不可变类。
      这里写图片描述
  • 缓存实例的不可变类

    • 如果程序经常需要使用相同的不可变类实例,则应考虑缓存这种不可变类的实例。

5. 抽象类

  • 抽象方法和抽象类
    这里写图片描述

  • 抽象类的作用

    • 从多个具有相同特征的类中抽象出一个抽象类,以这个抽象类作为其子类的模板,从而避免了子类设计的随意性

    • 抽象类体现的就是一种模板模式的设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展、改造,但子类总体上会保留抽象类的行为方式。

  • 模板方法设计模式,规则

    • 抽象父类可以只定义需要使用的某些方法,把不能实现的部分抽象成抽象方法,留给其子类去实现。

    • 父类中可能包含需要调用其他系列方法的方法,这些被调用方法既可以由父类实现,也可以由其子类实现。父类里提供的方法只是定义一个通过算法,其实现也许并不完全由自身实现,而必须依赖于其子类的辅助。

6. 接口

  • 接口的概述

    • 由于接口定义的是一种规范,因此接口里不能包含构造器和初始化块定义

    • 对于接口里定义的静态常量而言,它们是接口相关的,因此系统会自动为这些成员变量增加static和final两个修饰符。

  • 接口的继承

    • 接口完全支持多继承,多个父接口之间用英文逗号隔开。
  • 使用接口

    • 一个类可以实现一个或多个接口,继承使用extends关键字,实现则使用implements关键字

    • 一个类实现了一个或多个接口之后,这个类必须完全实现这些接口里所定义的全部抽象方法;否则,该类将保留从父类接口那里继承到的抽象方法,该类也必须定义成抽象类。

    • 实现接口方法时,必须使用public访问控制修饰符,因为接口里的方法都是public的,而子类重写父类方法时访问权限只能更大或者相等,所以实现类实现接口里的方法时只能使用public访问权限。

  • 接口和抽象类区别
    这里写图片描述

  • 面向接口编程
    (详情请见本人的“设计模式”分类下的相关文章)

    • 简单工厂模式

    • 命令模式

    • 代理模式

7. 内部类

  • 内部类作用

这里写图片描述
- 非静态内部类

-   在非静态内部类里**可以直接访问外部类的private成员**

这是因为在非静态内部类对象里,保存了一个它所寄生的外部类对象的引用(当调用非静态内部类的实例方法时,必须有一个非静态内部类实例,非静态内部类实例必须寄生在外部类实例里)。

  • 变量的访问

当在非静态内部类的方法内访问某个变量时,系统优先在该方法内查找是否存在该名字的局部变量,如果存在就使用该变量;如果不存在,则到该方法所在的内部类中查找是否存在该名字的成员变量,如果存在则使用该成员变量;如果不存在,则到该内部类所在的外部类中查找是否存在该名字的成员变量,如果存在则使用该成员变量;如果依然不存在,系统将出现错误:提示找不到该变量。

  • 内部类成员

非静态内部类的成员只在非静态内部类范围内是可知的,并不能被外部类直接使用。如果外部类需要访问非静态内部类的成员,则必须显示创建非静态内部类对象来调用访问其实例成员。

  • 非静态内部类不能有静态方法、静态成员变量、静态初始化块。

  • 静态内部类

    • 外部类依然不能直接访问静态内部类的成员,但可以使用静态内部类的类名作为调用者来访问静态内部类的类成员,也可以使用静态内部类对象作为调用者来访问静态内部类的实例成员。

    • java还允许在接口里定义内部类,接口里定义的内部类默认使用public
      static修饰,也就是说,接口内类只能是静态内部类。

  • 使用内部类

    • 在外部类内部使用内部类

与平常使用普通类一样

  • 在外部类以外使用非静态内部类

Out.In in = new Out().new In();

  • 在外部类以外使用静态内部类

Out.in in = new Out.In();

  • 局部内部类

    • 定义在方法内的类

    • 不能使用访问控制修饰符

  • 匿名内部类

    • 规则

      • 匿名内部类不能是抽象类,因为系统在创建匿名内部类时,会立即创建匿名内部类的对象。因此不允许将匿名内部类定义成抽象类。

      • 匿名内部类不能定义构造器。由于匿名内部类没有类名,所以无法定义构造器,但匿名内部类可以定义初始化块,可以通过实例初始化块来完成构造器需要完成的事情。

    • 细节

      • 在Java8之前,Java要求被局部内部类、匿名内部类访问的局部变量必须使用final修饰,从Java8开始这个限制被取消了,Java8更加智能:如果局部变量被匿名内部类访问,那么该局部变量相当于自动使用了final修饰
0 0