Java面向对象

一、类与对象

  • 创建一个类时要采用以下的形式:比如有一个叫Clock的类,则创建一个类则是Clock clock = new Clock();
  • 一个类含有成员函数和成员变量,在调用成员变量和成员函数时要用对象来调用。
  • 在初始化成员变量的时候,可以采用构造函数的形式,形如:
public Clock(int value){
	this.value = value;
}
public Clock(){
	value = 0;
}

构造函数可以有多个,根据具体情况调用不同的构造函数。上述两个构造函数构成重载关系。构造函数会在对象在创建的时候被调用。若没有对成员变量进行初始化,则成员变量就会被默认初始化成0值

  • 隐藏this
  • 一个java文件只能有一个public类

二、对象交互

  • 成员变量一般设计成private属性,成员函数一般设计成public属性,private属性成员变量只能在类的内部被访问,出了类外面就不能被访问,而public成员函数则可以在类外面被访问。(待续,有待补充)
  • 包。包就是Java的类库管理机制,它借助文件系统的目录来管理类库,一个包就是一个目录,一个包内的所有的类必须放在一个目录下,那个目录的名字必须是包的名字。
    非public成员只能在包内能被访问,而public成员则能在包外也可以被访问。
  • 类变量和类函数
    在变量前面加上static则是类变量,类变量属于类而不是对象,且类变量可以用类直接访问。而在函数前面加上static则是类函数,类函数也可以用类直接访问。而一般的main函数就是类函数。
    类函数由于不属于任何对象,因此也没有办法建立与调用它们的对象的关系,就不能访问任何非static的成员变量和成员函数了。

三、对象容器

Java有很多有用的容器,直接使用它们比自己设计一个个相似的要好的多。

  • ArrayList相当于一个数组,但与数组不同的是,放入其中的不是对象,而是指向对象的地址,相当与引用,即管理者。其输出顺序与放入顺序一致。
  • HashSet相当于一个集合,里面的数据无序,且唯一。任何一个类实现了public String toString(){ return ""; }函数,则直接可以输出这个类,会直接调用这个函数。
  • HashMap哈希表,构成<关键字, 值>的形式,且在添加关键字相同的值时,只会保存最后一次的结果,关键字是唯一的。

四. 继承与多态

1. 继承

我们把用来做基础派生其它类的那个类叫做父类、超类或者基类,而派生出来的新类叫做子类。Java用关键字extends表示这种继承/派生关系:

class Thisclass extends superclass {
	//.......
}

子类的对象可以被看作是父类的对象,Java的继承只允许单继承,即一个类只能有一个父类。
所有的父类的成员,包括变量和方法,都成为了子类的成员,除了构造方法。
下表列出了不同访问属性的父类成员在子类中的访问属性:

父类成员访问属性 在父类中的含义 在子类中的含义
public 对所有人开放 对所有人开放
protected 只有包内其它类、自己和子类可以访问 只有包内其它类、自己和子类可以访问
缺省 只有包内其它类可以访问 如果子类与父类在同一个包内:只有包内其它类可以访问,否则:相当于private,不能访问
private 只有自己可以访问 不能访问

在构造一个子类的对象时,父类的构造方法也是会被调用的,而且父类的构造方法在子类的构造方法之前被调用。在程序运行过程中,子类对象的一部分空间存放的是父类对象。因为子类从父类得到继承,在子类对象初始化过程中可能会使用到父类的成员。所以父类的空间正是要先被初始化的,然后子类的空间才得到初始化。在这个过程中,如果父类的构造方法需要参数,如何传递参数就很重要了。

子类若是定义了与父类一样的私有变量,则子类与父类的变量互不相关,不相互影响.

子类没有显示调用父类构造函数,不管子类构造函数是否带参数都默认调用父类无参的构造函数,若父类没有则编译出错。

2. 多态和向上造型

当把一个对象赋值给一个变量时,对象的类型必须与变量的类型相匹配,如:
Car myCar = new Car();
是一个有效的赋值,因为Car类型的对象被赋值给声明为保存Car类型对象的变量。但是由于引入 了继承,这里的类型规则就得叙述得更完整些:

一个变量可以保存其所声明的类型或该类型的任何子类型。

对象变量可以保存其声明的类型的对象,或该类型的任何子类型的对象。

Java中保存对象类型的变量是多态变量。“多态”这个术语(字面意思是许多形态)是指一个变量可以保存不同类型(即其声明的类型或任何子类型)的对象。

Item item = new Item();
DVD dvd = new DVD();
item = dvd;
DVD dvd1 = (DVD)item;

上面中的Item是DVD的父类,则子类的对象可以赋给父类,即item可以指向dvd,但在将item赋给dvd1时,需要对item进行造型,即item需要是DVD类型的,才可以进行这种造型.而且,在Java中是不存在一个对象赋给另一个对象的,并且将一个父赋给自类也是不允许的.

3. 多态

在对一个对象变量进行调用函数时,会出现静态绑定和动态绑定情况,具体的函数调用会根据这个变量来进行,即在运行时进行判定.
@override表示覆盖.在进行覆盖的时候要注意几点:
(1). 重写方法必须和被重写方法具有相同的参数列表,返回类型必须和被重写方法的返回类型相同或者是返回类型的子类型。
(2).重写方法的访问控制修饰符不能比被重写方法更严格(比如一个在父类中声明为public的方法重写成一个protected的方法)。
(3). 只有实例方法才能被重写,超类中的static和final方法不能被重写。
(4). 重写方法不能抛出新的检查异常,或者是抛出比被重写方法声明的检查异常更广泛的检查异常。
(5). 注意一种特殊情况:如果超类的方法版本中声明了检查异常,但重写的子类方法中没有声明,这时如果使用多态的方式进行调用,那么编译器认为你调用的是声明了异常的方法。
(6). 尽管多态是在编译时确定对象的类型,但在编译时,还是根据父类的方法声明进行程序检查。因此,如果子类中定义的方法,在父类中没有定义,则会出现编译错误。

4. Object类

任何一个类都是Object类的子类,且

toString()
equals()

都是Object类的函数,在实现自己的功能时,需要对上述两个函数进行重写.

5. super和this的异同:

1. super(参数):调用基类中的某一个构造函数(应该为构造函数中的第一条语句) 
2. this(参数):调用本类中另一种形成的构造函数(应该为构造函数中的第一条语句)
3. super: 它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员数据或函数,基类与派生类中有相同成员定义时如:super.变量名    super.成员函数据名(实参)
4. this:它代表当前对象名(在程序中易产生二义性之处,应使用this来指明当前对象;如果函数的形参与类中的成员数据同名,这时需用this来指明成员变量名)
5. 调用super()必须写在子类构造方法的第一行,否则编译不通过。每个子类构造方法的第一条语句,都是隐含地调用super(),如果父类没有这种形式的构造函数,那么在编译的时候就会报错。
6. super()和this()类似,区别是,super()从子类中调用父类的构造方法,this()在同一类内调用其它方法。
7. super()和this()均需放在构造方法内第一行。
8. 尽管可以用this调用一个构造器,但却不能调用两个。
9. this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。
10. this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块。
11. 从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字.

五. 设计原则

  • 减少重复代码
  • 用封装来降低耦合
  • 用接口来实现聚合
  • 以框架+数据来提高可扩展性

六. 抽象与接口

1. 抽象

  • 抽象函数---表达感念而无法实现具体代码的函数
  • 抽象类---表达感念而无法构造出实体的类
  • 带有abstract修饰符的函数
  • 有抽象函数的类一定是抽象类
  • 抽象类不能制造对象,但可以定义变量,任何继承了抽象类的非抽象类对象可以赋给这个变量.
  • 继承自抽象类的子类必须覆盖父类中的抽象函数,否则自己成为抽象类

数据与表现分离.责任驱动设计.网格化

2. 接口

  • 接口用extends,接口用implements
  • 类可以实现很多接口
  • 接口可以继承接口,但不能继承类
  • 接口不能实现接口
  • 接口支持多继承
  • 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。
  • 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)。
  • 一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。

3. 面向接口编程

  • 设计程序时先定义接口,再实现类
  • 任何需要在函数间传入传出的一定是接口而不是具体的类
  • 是Java成功的关键之一,因为极适合多人写一个大程序
  • 也是Java被批评的要点之一,因为代码膨胀起来很快

七. 控制反转与MVC

1. 控制反转

布局是指如何在屏幕上放置组件。过去,大多数简单的GUI系统让程序员在二维坐标系上 指定每个组件的x和y坐标(以像素点为单位),这对于现代的GUI系统来说太简单了。因为现代的GUI系统还得考虑不同的屏幕分辨率、不同的字体、用户可改变的窗口尺寸,以及许多其他使得布局困难的因素。所以需要有一种能更通用地指定布局的方法,比如,要求“这个部件应该在那个部件的下面“或者”这个部件在窗口改变尺寸时能自动拉伸,但是其他部件保持尺寸不变”。这些可以通过布局管理器(layout manager)来实现。

事件处理是用来响应用户输入的技术。创建了部件并且放在屏幕上合适的位置以后,就得 要有办法来处理诸如用户点击按钮这样的事情。Java类库处理这类事情的模型是基于事件的。 如果用户激活了一个部件(比如,点击按钮或者选择菜单项),系统就会产生一个事件。应用 程序可以收到关于这个事件的通知(以程序的一个方法被调用的方式),然后就可以采取程序该做的动作了。

Swing使用一个非常灵活的模型来处理GUI的输入:采用事件监听器的事件处理(event handling)模型。

Swing框架本身以及大部分部件在发生一些情况时会触发相关的事件,而其他的对象也许会对这些事件感兴趣。不同类型的动作会导致不同类型的事件。当点击一个按钮或选中一个菜单项,部件就会触发动作事件;而当点击或移动鼠标时,会触发鼠标事件;当框架被关闭或最小化时,会触发窗口事件。另外还有许多种其他事件。

所有的对象都可以成为任何这些事件的监听器,而一旦成为监听器,就可以得到这些事件触发的通知。

实现了众多监听器接口之一的对象就成为一个事件监听器。如果对象实现了恰当的接口, 就可以注册到它想监听的组件上。

  • 由按钮公布一个守听者接口和一对注册/注销函数
  • 你的代码实现那个接口,将守听者对象注册在按钮上
  • 一旦按钮被按下,就会反过来调用你的守听者对象的某个函数

2. 内部类

  • 定义在别的类内部.函数内部
  • 内部类能直接访问外部的所有资源
    • 包括任何私有的成员
    • 外部是函数时,只能访问那个函数里面的final变量
public class FoxAndRabbit {
	/*   变量   */
	
	/*   成员函数   */
	
	// 以下就是内部类
	class StepListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent e) {
			/*    相应操作   */
		}
	}
}

3. 匿名内部类(很好用)

  • 匿名类是特殊的内部类,访问权限与内部类一样
  • 在new对象的时候给出类的定义形成了匿名类
  • 匿名类可以继承某类,也可以实现某接口
  • Swing的消息机制广泛使用匿名类,省去给类取名字的麻烦
btnStep.addActionListener(new ActionListener() {
	@Override
	public void actionPerformed(ActionEvent e) {
		/*  执行相应操作 */
	}
});

4.MVC设计模式

  • 数据.表现和控制三者分离,各负其责
    • M = Model (模型)
    • V = View (表现)
    • C = Control (控制)
  • 模型:保存和维护数据,提供接口让外部修改数据,通知表现需要刷新
  • 表现:从模型获得数据,根据数据画出表现
  • 控制:从用户得到输入,根据输入调整数据

八. 异常处理与输入输出

1. 异常处理

2. 异常类处理函数

  • String getMessage()
  • String toString()
  • void printStackTrace()

注意点:

  • 当catch里面无法处理异常时,可以再度抛出异常,用关键字throw.
  • 异常机制的最大好处是清晰地分开了正常的业务逻辑代码和遇到情况时的处理代码

3. 异常申明

  • 如果你的函数可能会抛出异常,就必须在函数头部加以申明
void f() throws toobig, toosmall, divzero {  /*  操作 */}
  • 你可以申明,但不会真的抛出异常
  • Exception继承了Throwable
    • throw new Exception();
    • throw new Exception("new");

4.异常匹配机制

  • Is-A关系,就是说,抛出子类异常会被捕捉父类异常的catch给捉到
  • 一个通用父类可以派生出各种异常类,如果一个catch块可以捕获一个父类的异常对象,它就能捕获那个父类的所有子类的异常对象。如果捕获的是多个同类型异常,则子类异常在前,父类异常在后,不然会导致编译错误。这是因为父类异常囊括了子类异常,如果父类异常在前,子类异常永远捕获不到,导致有时候无法准确描述错误信息。
  • 当覆盖一个函数时,子类不能声明抛出比父类的版本更多的异常
  • 在子类的构造函数中,必须申明父类可能抛出的所有异常

5. 流

字节流(二进制数据)

  • InputStream
  • OutputStream

文件流

  • FileInputStream
  • FileOutputStream

Data(用以读写二进制方式表达的基本类型的数据)

  • DataInputStream
  • DataOutputStream

  • 对象串行化,将对象放进文件或流中

补充

  • nextLine()方法返回的是Enter键之前的所有字符,方法的结束符只是Enter键。
  • next()会自动消去有效字符前的空格,只返回输入的字符,在输入有效字符之后,将其后输入的空格键、Tab键或Enter键等视为分隔符或结束符。
  • read()函数是阻塞的
  • java只是值传递
posted @ 2019-01-12 00:32  你好,果果  Views(130)  Comments(0Edit  收藏  举报