VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > Java教程 >
  • Java编程的逻辑-面向对象

 

类的基础

 

构造方法

 

  1. 名称是固定的,与类名相同。这也容易理解,靠这个用户和 Java系统就都能容易地知道哪些是构造方法。
  2. 没有返回值,也不能有返回值。构造方法隐含的返回值就是实例本身。

 

创建对象后的内存

 

对象和数组一样,有两块内存,保存地址的部分分配在栈中,而保存实际内容的部分分配在堆中。栈中的内存是自动管理的,函数调用入栈就会分配,而出栈就会释放。

 

this and super

 

  1. 我们前面解释说 this表示当前实例,可以通过 this访问实例变量,这是 this的第二个用法,用于在构造方法中调用其他构造方法。
  2. super的使用与 this有点像,但 super和 this是不同的, this引用一个对象,是实实在在存在的,可以作为函数参数,可以作为返回值,但 super只是一个关键字,不能作为参数和返回值,它只是用于告诉编译器访问父类的相关变量和方法。

 

 

继承和多态

 

 

转型

 

子类对象赋值给父类引用变量,这叫向上转型,转型就是转换类型,向上转型就是转换为父类类型。

 

 

多态

 

父类对象可以引用任何子类类型的对象,这叫多态,即一种类型的变量,可引用多种实际类型对象。这样,对于父类对象,它就有两个类型:声明时的父类自身类型,我们称之为静态类型;实际引用的子类类型,我们称之为动态类型。实际调用的方法也是引用类型(动态类型)的方法,这称之为方法的动态绑定。

 

 

继承中的初始化

 

  1. new过程中,父类先进行初始化,可通过 super 调用父类相应的构造方法,没有使用 super 的情况下,调用父类的默认构造方法。
  2. 父类只有一个带参数的构造方法,没有默认构造方法。这个时候,它的任何子类都必须在构造方法中通过 super 调用 Base的带参数构造方法,否则, Java会提示编译错误。

 

 

父类构造方法中调用可被子类重写的方法(不推荐)

 

在 new过程中,首先是初始化父类,父类构造方法调用 test() 方法, test() 方法被子类重写了,就会调用子类的 test() 方法,子类方法访问子类实例变量 a,而这个时候子类的实例变量的赋值语句和构造方法还没有执行,所以输出的是其默认值 0。
像这样,在父类构造方法中调用可被子类重写的方法,是一种不好的实践,容易引起混淆,应该只调用 private的方法。

 

 

子类和父类中方法or变量重名

 

  1. 方法或变量重名是可以的,重名后实际上有两个变量或方法。 private变量和方法只能在类内访问,访问的也永远是当前类的,即:在子类中访问的是子类的;在父类中访问的是父类的,它们只是碰巧名字一样而已,没有任何关系。
  1. public变量和方法,则要看如何访问它。在类内,访问的是当前类的,但子类可以通过 super.明确指定访问父类的。在类外,则要看访问变量的静态类型:静态类型是父类,则访问父类的变量和方法;静态类型是子类,则访问的是子类的变量和方法。

 

 

静态绑定

 

静态绑定,即访问绑定到变量的静态类型。静态绑定在程序编译阶段即可决定,而动态绑定则要等到程序运行时。实例变量、静态变量、静态方法、 private方法,都是静态绑定的。

 

可以看出,当有多个重名函数的时候,在决定要调用哪个函数的过程中,首先是按照参数类型进行匹配的,换句话说,寻找在所有重载版本中最匹配的,然后才看变量的动态类型,进行动态绑定。

 

一个父类的变量能不能转换为一个子类的变量,取决于这个父类变量的动态类型(即引用的对象类型)是不是这个子类或这个子类的子类。
给定一个父类的变量能不能知道它到底是不是某个子类的对象,从而安全地进行类型转换呢?答案是可以,通过 instanceof关键字。

 

 

重写时,子类方法不能降低父类方法的可见性。

 

为什么要这样规定呢?继承反映的是“ is-a”的关系,即子类对象也属于父类,子类必须支持父类所有对外的行为,将可见性降低就会减少子类对外的行为,从而破坏“ is-a”的关系,但子类可以增加父类的行为,所以提升可见性是没有问题的。

 

 

类加载

 

所谓类的加载是指将类的相关信息加载到内存。在 Java中,类是动态加载的,当第一次使用这个类的时候才会加载,加载一个类时,会查看其父类是否已加载,如果没有,则会加载其父类。

 

 

类加载后的内存分配

 

内存分为栈和堆,栈存放函数的局部变量,而堆存放动态分配的对象,还有一个内存区,存放类的信息,这个区在 Java中称为方法区。

 

 

方法调用

 

寻找要执行的实例方法的时候,是从对象的实际类型信息开始查找的,找不到的时候,再查找父类类型信息。
动态绑定实现的机制就是根据对象的实际类型查找要执行的方法,子类型中找不到的时候再查找父类。

 

 

变量访问的过程

 

对变量的访问是静态绑定的,无论是类变量还是实例变量。

 

 

接口的威力

 

场景:Comparable 接口,自定义的类(P)如果有比较的需求,实现这个接口,重写 compareTo 方法,这样就可以p1.compareTo(p2)使用了,再进一步来说,当你需要针对一个集合(实现了 Comparable 接口)进行排序,或者输出最大值,最小值的时候,可以定义一个 CompUtil 的类,来针对 Comparable 接口进行编程(可以生命为接口类型,但是实际类型为实现了接口的类型,如 Comparable p = new P()

 

  1. 接口的变量都是 public static final 的,可以省略
  2. 一个接口可以有多个父接口
  3. 类的继承可以和接口共存,extends 要在 implements 前面
  4. 可以用 instanceof 判断一个类是否实现了某个接口

 

 

Java 8 新增

 

接口中可以定义,静态方法和默认方法

 

 

抽象类

 

例如:图形类 Shape,它有一个方法 draw() 。Shape其实是一个抽象概念,它的 draw() 方法其实并不知道如何实现,只有子类才知道。这种只有子类才知道如何实现的方法,一般被定义为抽象方法。

 

定义了抽象方法的类必须被声明为抽象类,不过,抽象类可以没有抽象方法。抽象类和具体类一样,可以定义具体方法、实例变量等,它和具体类的核心区别是,抽象类不能创建对象,而具体类可以。

 

Shape shape = new Circle(); 
shape.draw();

 

shape 是抽象类 Shape类型的变量,引用了具体子类 Circle的对象,调用 draw() 方法将调用 Circle 的 draw代码。

 

 

为什么需要抽象类

 

引入抽象方法和抽象类,是 Java提供的一种语法工具,对于一些类和方法,引导使用者正确使用它们,减少误用。

 

无论是编写程序,还是平时做其他事情,每个人都可能会犯错,减少错误不能只依赖人的优秀素质,还需要一些机制,使得一个普通人都容易把事情做对,而难以把事情做错。抽象类就是 Java提供的这样一种机制。

 

 

内部类

 

内部类只是 Java编译器的概念,对于 Java虚拟机而言,它是不知道内部类这回事的,每个内部类最后都会被编译为一个独立的类,生成一个独立的字节码文件。

 

静态内部类使用场景:一个类内部,如果既要计算最大值,又要计算最小值,可以在一次遍历中将最大值和最小值都计算出来,但怎么返回呢?可以定义一个类 Pair,包括最大值和最小值,但 Pair这个名字太普遍,而且它主要是类内部使用的,就可以定义为一个静态内部类。

 

成员内部类使用场景:成员内部类有哪些应用场景呢?如果内部类与外部类关系密切,需要访问外部类的实例变量或方法,则可以考虑定义为成员内部类。外部类的一些方法的返回值可能是某个接口,为了返回这个接口,外部类方法可能使用内部类实现这个接口,这个内部类可以被设为 private,对外完全隐藏。

 

 

枚举

 

  1. 枚举变量可以使用 equals和 = =进行比较,结果是一样的。
  2. 枚举值是有顺序的,可以比较大小。枚举类型都有一个方法 int ordinal(),表示枚举值在声明时的顺序,从 0开始。
  3. 枚举可以比较,其实就是比较 ordinal的大小。
  4. 枚举类型都有一个静态的 valueOf(string),返回指定的枚举值。
  5. 枚举类型也都有一个静态的 values方法,返回一个包括所有枚举值的数组,顺序与声明时的顺序一致。


原文链接:https://www.5axxw.com/wenku/1j/5100989z.html

相关教程