java基础知识点

java基础知识点

对java多态的理解

什么是多态

  1. 面向对象的三大特性:封装、继承、多态。从一定角度来看,封装和继承几乎都是为多态而准备的。这是我们最后一个概念,也是最重要的知识点。
  2. 多态的定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)

  3. 实现多态的技术称为:动态绑定(dynamic binding),是指在执行期间判断所引用对象的实
    际类型,根据其实际的类型调用其相应的方法。

  4. 多态的作用:消除类型之间的耦合关系。

多态存在的三个必要条件

  • 要有继承;
  • 要有重写;
  • 父类引用指向子类对象。

多态的好处:

  1. 可替换性(substitutability)。多态对已存在代码具有可替换性。例如,多态对圆Circle类工作,对其他任何圆形几何体,如圆环,也同样工作。

  2. 可扩充性(extensibility)。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性。

  3. 接口性(interface-ability)。多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。如图8.3 所示。图中超类Shape规定了两个实现多态的接口方法,computeArea()以及computeVolume()。子类,如Circle和Sphere为了实现多态,完善或者覆盖这两个接口方法。

  4. 灵活性(flexibility)。它在应用中体现了灵活多样的操作,提高了使用效率。

  5. 简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。

java中==和equals和hashCode的区别

三个的基本概念

  • ==:==是运算符,用于比较两个变量是否相等。
  • equals: equals,是Objec类的方法,用于比较两个对象是否相等,默认Object类的equals方法是比较两个对象的地址,跟==的结果一样。
  • hashCode: hashCode也是Object类的一个方法。返回一个离散的int型整数。在集合(HashMap,HashSet等)类操作中使用,为了提高查询速度。

数据类型的比较

  • 基本数据类型 ,也称原始数据类型。byte, short, char, int, long, float, double, boolean他们之间的比较,应用双等号(==),比较的是他们的值。
  • 复合数据类型(类) 当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址,所以,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。 JAVA当中所有的类都是继承于Object这个基类的,在Object中的基类中定义了一个equals的方法,这个方法的初始行为是比较对象的内存地 址,但在一些类库当中这个方法被覆盖掉了,如String, Integer, Date在这些类当中equals有其自身的实现,而不再是比较类在堆内存中的存放地址了。所以,对于复合数据类型之间进行equals比较,在没有覆写equals方法的情况下,他们之间的比较还是基于他们在内存中的存放位置的地址值的,因为Object的equals方法也是用双等号(==)进行比较的,所以比较后的结果跟双等(==)的结果相同。
  • 对于两个对象 如果两个对象根据equals()方法比较是相等的,那么调用这两个对象中任意一个对象的hashCode方法都必须产生同样的整数结果。如果两个对象根据equals()方法比较是不相等的,那么调用这两个对象中任意一个对象的hashCode方法,则不一定要产生相同的整数,从而在集合操作的时候有如下规则:将对象放入到集合中时,首先判断要放入对象的hashcode值与集合中的任意一个元素的hashcode值是否相等,如果不相等直接将该对象放入集合中。如果hashcode值相等,然后再通过equals方法判断要放入对象与集合中的任意一个对象是否相等,如果equals判断不相等,直接将该元素放入到集合中,否则不放入。

关于equals和hashCode的使用

  • 在覆盖equals方法的时候 需要遵循的规则:
    • 自反性。对于任何非null的引用值x,x.equals(x)必须返回true。
    • 对称性。对于任何非null的引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)必须返回true
    • 传递性。对于任何非null的引用值x、y和z,如果x.equals(y)返回true,并且y.equals(z)也返回true,那么x.equals(z)也必须返回true。
    • 一致性。对于任何非null的引用值x和y,只要equals的比较操作在对象中所用的信息没有被修改,多次调用该x.equals(y)就会一直地返回true,或者一致地返回false。
    • 对于任何非null的引用值x,x.equals(null)必须返回false。
  • 结合以上要求,得出了以下实现高质量equals方法的诀窍:
    1. 使用==符号检查“参数是否为这个对象的引用”。如果是,则返回true。这只不过是一种性能优化,如果比较操作有可能很昂贵,就值得这么做。
    2. 使用instanceof操作符检查“参数是否为正确的类型”。如果不是,则返回false。一般来说,所谓“正确的类型”是指equals方法所在的那个类。
    3. 把参数转换成正确的类型。因为转换之前进行过instanceof测试,所以确保会成功。
    4. 对于该类中的每个“关键”域,检查参数中的域是否与该对象中对应的域相匹配。如果这些测试全部成功,则返回true;否则返回false。
    5. 当编写完成了equals方法之后,检查“对称性”、“传递性”、“一致性”。
  • equals和hashCode的具体使用
    一个很常见的错误根源在于没有覆盖hashCode方法。在每个覆盖了equals方法的类中,也必须覆盖hashCode方法。如果不这样做的话,就会违反Object.hashCode的通用约定,从而导致该类无法结合所有基于散列的集合一起正常运作,这样的集合包括HashMap、HashSet和Hashtable。在应用程序的执行期间,只要对象的equals方法的比较操作所用到的信息没有被修改,那么对这同一个对象调用多次,hashCode方法都必须始终如一地返回同一个整数。在同一个应用程序的多次执行过程中,每次执行所返回的整数可以不一致。如果两个对象根据equals()方法比较是相等的,那么调用这两个对象中任意一个对象的hashCode方法都必须产生同样的整数结果。如果两个对象根据equals()方法比较是不相等的,那么调用这两个对象中任意一个对象的hashCode方法,则不一定要产生相同的整数结果。但是程序员应该知道,给不相等的对象产生截然不同的整数结果,有可能提高散列表的性能。

String、StringBuffer、StringBuilder区别

定义

  • String: String 字符串常量
  • StringBuffer: StringBuffer 字符串变量(线程安全)
  • StringBuilder: StringBuilder 字符串变量(非线程安全)

使用String和StringBuffer的区别

简要的说, String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象, 因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后,JVM的GC垃圾处理线程就会开始工作,那速度是一定会相当慢的。而如果是使用 StringBuffer 类则结果就不一样了,每次结果都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,再改变对象引用。所以在一般情况下我们推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下。而在某些特别情况下,String 对象的字符串拼接其实是被 JVM 解释成了 StringBuffer 对象的拼接,所以这些时候 String 对象的速度并不会比 StringBuffer 对象慢,而特别是以下的字符串对象生成中, String 效率是远要比 StringBuffer 快。

关于StringBuffer的知识

Java.lang.StringBuffer线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。
StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;insert 方法则在指定的点添加字符。

内部类的作用

  • 作用:
    1. 内部类可以用多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立。
    2. 在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或者继承同一个类。
    3. 创建内部类对象的时刻并不依赖于外围类对象的创建。
    4. 内部类并没有令人迷惑的“is-a”关系,他就是一个独立的实体。
    5. 内部类提供了更好的封装,除了该外围类,其他类都不能访问。

抽象类和接口

两者的区别

  • 默认的方法实现

    • 抽象类可以有默认的方法实现完全是抽象的。接口根本不存在方法的实现。
  • 实现

    • 子类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现。
      子类使用关键字implements来实现接口。它需要提供接口中所有声明的方法的实现。
  • 构造器

    • 抽象类可以有构造器,接口不能有构造器
  • 与正常Java类的区别

    • 抽象类除了你不能实例化抽象类之外,它和普通Java类没有任何区,接口是完全不同的类型。
  • 访问修饰符

    • 抽象方法可以有public、protected和default这些修饰符,接口方法默认修饰符是public。你不可以使用其它修饰符。
  • main方法

    • 抽象方法可以有main方法并且我们可以运行它,接口没有main方法,因此我们不能运行它。
  • 多继承

    • 抽象类在java语言中所表示的是一种继承关系,一个子类只能存在一个父类,但是可以存在多个接口。
  • 速度

    • 抽象类它比接口速度要快,接口是稍微有点慢的,因为它需要时间去寻找在类中实现的方法。
  • 添加新方法

    • 如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。如果你往接口中添加方法,那么你必须改变实现该接口的类。

抽象的意义

  1. 为其子类提供一个公共的类型。
  2. 封装子类中得重复内容。
  3. 定义抽象方法,子类虽然有不同的实现 但是定义是一致的。

注意点

  • 父类的静态方法不能被子类重写。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值