套用linux“一切皆文件”的思想,Java语言可以说一切皆对象。因此,学习 Java 语言必须掌握对象(实质上类可以看作是对象的抽象,它定义了对象的具体属性和方法),这样可以从深层次理解 Java 这种面向对象语言的幵发理念。
一、对象的概念
所谓对象就是真实世界中的实体,对象与实体是一一对应的,也就是说现实世界中每一个实体都是一个对象,它是一种具体的概念。
对象有以下特点:
对象具有属性和行为。
对象具有变化的状态。
对象具有唯一性。
对象都是某个类别的实例。
一切皆为对象,真实世界中的所有事物都可以视为对象。
向对象程序设计有以下优点:
1. 可重用性:它是面向对象软件开发的核心思路,提高了开发效率。面向对象程序设计的抽象、继承、封装和多态四大特点都围绕这个核心。
2. 可扩展性:它使面向对象设计脱离了基于模块的设计,便于软件的修改。
3. 可管理性:能够将功能与数据结合,方便管理。
二、Java继承
继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
继承的语法格式:
class 父类名 {
}
class 子类名 extents 父类名 {
}
继承的优势:提高代码的复用性,易于维护。
2.1. 继承的特性:
1. 子类具有父类非private的属性和方法
2. 子类可以扩展父类没有的方法
3. 子类可以用自己的方法实现父类的方法
4. Java的继承是单继承和多重继承,不支持多继承
2.2 关键字
1. 继承的关键字:extends和implements来实现继承。而且所有的类都是继承于 java.lang.Object,当一个类没有继承的两个关键字,则默认继承object(这个类在 java.lang 包中,所以不需要 import)祖先类。
2 super 与 this 关键字:
super:通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
this:指向自己的引用。
3. final关键字:
final 关键字声明类可以把类定义为不能继承的,即最终类;或者用于修饰方法,该方法不能被子类重写:
声明类语法格式:
final class 类名 {
//类体
}
2.3 Java构造器
构造器的注意事项:
1.构造器的名称必须和类名一致;
2.一个类中可以定义多个构造器,但是构造器的参数列表必须不同;
3.如果我们没有手动定义构造器,则java系统会提供一个默认的构造器给我们使用。一旦我们定了构造器,则系统会把构造器收回;
4.构造器的作用:实例化对象,给对象赋初始值;
5.代码游离块优先执行。
2.4 instanceof 关键字
可以使用 instanceof 运算符来检验一个子类是否是一个父类的一个实例。
参考实例:
public class MyClassTest {
public static void main(String[] args) {
System.out.println("Show class info:");
Dog dog = new Dog("qiuqiu", 1);
dog.eat();
dog.sleep();
dog.showInfo();
dog.look();
Mouse mouse = new Mouse("xixi", 2);
mouse.eat();
mouse.sleep();
mouse.showInfo();
mouse.action();
System.out.println(dog instanceof Animal);
System.out.println(mouse instanceof Animal);
}
}
/*
* 父类
*/
class Animal {
private String priName;
private int priId;
//构造器
public Animal(String name, int id) {
priName = name;
priId = id;
}
public void eat() {
System.out.println(priName + " eating!");
}
public void sleep() {
System.out.println(priName + " sleeping!");
}
public void showInfo() {
System.out.println("name is " + priName + " id " + priId);
}
}
/*
* 子类
*/
class Dog extends Animal {
public Dog (String name, int id) {
super(name, id);
}
public void look() {
System.out.println("看家");
}
}
/*
* 子类
*/
class Mouse extends Animal {
public Mouse(String name, int id) {
super(name, id);
}
public void action() {
System.out.println("搞破坏");
}
}
输出结果:
Show class info:
qiuqiu eating!
qiuqiu sleeping!
name is qiuqiu id 1
看家
xixi eating!
xixi sleeping!
name is xixi id 2
搞破坏
true
true
注意:
Java不支持多继承,但支持多重继承。
class A {
}
class B {
}
//单继承
class C extends A{
}
//多重继承
class D extends C{
}
//单继承
class E extends A{
}
//class F多继承,非法
class F extends A, B{
}
三、Java多态
多态是同一种行为具有多种不同的表现形式。Java中,所有的对象都具有多态性。
比如我们说动物这个对象,他可以有多种表现形式,比如猫,狗等。当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
多态的优点
1. 消除类型之间的耦合关系
2. 可替换性
3. 可扩充性
4. 接口性
5. 灵活性
6. 简化性
多态存在的三个必要条件
继承
重写
父类引用指向子类对象
多态的实现方式
方式一:重写,重写(Override)与重载(Overload)。
方式二:接口
1. 生活中的接口最具代表性的就是插座,例如一个三接头的插头都能接在三孔插座中,因为这个是每个国家都有各自规定的接口规则,有可能到国外就不行,那是因为国外自己定义的接口类型。
2. java中的接口类似于生活中的接口,就是一些方法特征的集合,但没有方法的实现。具体可以看 java接口 这一章节的内容。
方式三:抽象类和抽象方法
四、抽象类
Java中所有对象都是用类来描述的,但不是所有的类都可以描述对象。如果一个类中,没有足够的信息来表示一个对象,这个类就是抽象类。由于抽象类不能实例化对象,所有抽象类必须被继承才能被使用。
抽象类规定:
1. 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。
2. 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
3. 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。
4. 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。
5. 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。
Java中使用abstract class来定义抽象类。
实例:
文件:Lesson2.java
package lesson2;
public class Lesson2 {
public static void main(String[] args) {
System.out.println("Lesson2 Class.");
//Students students = new Students("lili", "woman", 22);
//students.showInfo();
Yoyo stu1 = new Yoyo("yoyo", "girl", 22);
System.out.println(stu1.getAge());
stu1.setScore(99.8);
System.out.println(stu1.getScore());
System.out.println(stu1.getName());
System.out.println(stu1.getSex());
stu1.showInfo();
}
}
文件:Students.java
package lesson2;
public abstract class Students
{
private String name;
private int age;
private String sex;
public Students(String name, String sex, int age) {
System.out.println("构造器");
this.name = name;
this.sex = sex;
this.age = age;
}
public String getName() {
return name;
}
public String getSex() {
return sex;
}
public int getAge() {
return age;
}
public void showInfo() {
System.out.println("name is " + name + " age: " + age);
}
}
文件:Yoyo.java
package lesson2;
public class Yoyo extends Students {
private double score;
public Yoyo(String name, String sex, int age) {
super(name, sex, age);
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
}
输出结果:
Lesson2 Class.
构造器
22
99.8
yoyo
girl
name is yoyo age: 22
抽象方法
**如果你想设计这样一个类,该类包含一个特别的成员方法,该方法的具体实现由它的子类确定,那么你可以在父类中声明该方法为抽象方法**。
Abstract 关键字同样可以用来声明抽象方法,抽象方法只包含一个方法名,而没有方法体。
抽象方法没有定义,方法名后面直接跟一个分号,而不是花括号。
public abstract class Employee
{
private String name;
private String address;
private int number;
public abstract double computePay(); //抽象方法
//其余代码
}
注意:
声明抽象方法会造成以下两个结果:
1. 如果一个类包含抽象方法,那么该类必须是抽象类。
2. 任何子类必须重写父类的抽象方法,或者声明自身为抽象类。
继承抽象方法的子类必须重写该方法。否则,该子类也必须声明为抽象类。最终,必须有子类实现该抽象方法,否则,从最初的父类到最终的子类都不能用来实例化对象。
五、Java封装
封装是指一种将抽象性函式接口的实现细节部份包装、隐藏起来的方法。封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。要访问该类的代码和数据,必须通过严格的接口控制。
封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。
优点:
1. 良好的封装能够减少耦合。
2. 类内部的结构可以自由修改。
3. 可以对成员变量进行更精确的控制。
4. 隐藏信息,实现细节。
实例参考第四部分Java抽象类。
六、Java 重写(Override)重载(OverLoad)
1.重写
所谓重写就是子类对父类允许的方法的实现进行重新编写,但不能改变行参和返回值。
class Animal {
public void move() {
System.out.println("动物可以移动");
}
}
class Dog extends Animal {
//重写move
public void move() {
System.out.println("狗可以跑");
}
//子类独有方法
public void bark() {
System.out.println("狗会叫");
}
}
class Fish extends Animal {
//重写move
public void move() {
super.move(); //调用父类方法。super关键字
System.out.println("鱼可以游");
}
}
public class MyClassTest {
public static void main(String[] args) {
System.out.println("Lession2: 重写");
Animal animal = new Animal();
Animal dog = new Dog();
Dog dog2 = new Dog();
Animal fish = new Fish();
animal.move();
dog.move();
//dog.bark(); //编译错误,因为父类没有bark()方法
dog2.bark();
dog2.move();
fish.move();
}
}
输出结果:
Lession2: 重写
动物可以移动
狗可以跑
狗会叫
狗可以跑
动物可以移动
鱼可以游
重写注意规则:
1. 参数列表必须完全与被重写方法的相同;
2. 返回类型必须完全与被重写方法的返回类型相同;
3. 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为public,那么在子类中重写该方法就不能声明为protected。
4. 父类的成员方法只能被它的子类重写。
5. 声明为final的方法不能被重写。
6. 声明为static的方法不能被重写,但是能够被再次声明。
7. 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为private和final的方法。
8. 子类和父类不在同一个包中,那么子类只能够重写父类的声明为public和protected的非final方法。
9. 重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
10. 构造方法不能被重写。
11. 如果不能继承一个方法,则不能重写这个方法。
Super关键字的使用
当需要在子类中调用父类的被重写方法时,要使用super关键字。
2. 重载(Overload)
重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。最常用的地方就是构造器的重载。
实例:
public void overload() {
System.out.println("overLoad");
}
public void overload(String name) {
System.out.println("overLoad " + name);
}
public void overload(int num) {
System.out.println("overLoad " + num);
}
static void MyOverLoad() {
MyClassTest ol = new MyClassTest();
ol.overload();
ol.overload(1);
ol.overload("lili");
}
输出结果:
overLoad
overLoad 1
overLoad lili
3. 重写和重载区别:
重载 重写
参数列表 必须修改 一定不能修改
返回类型 可以修改 一定不能修改
异常 可以修改 可以减少或删除,一定不能抛出新的或者更广的异常
访问 可以修改 一定不能做更严格的限制(可以降低限制)
七、Java接口
接口在Java中以Interface来声明,虽然接口的方法和类相似,但接口并不是类,他们属于不同的概念。接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。
7.1 接口特性
1. 口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。
2. 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)。
3. 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。
7.2 接口与类相似点:
1. 一个接口可以有多个方法。
2. 接口文件保存在 .java 结尾的文件中,文件名使用接口名。
3. 接口的字节码文件保存在 .class 结尾的文件中。
4. 接口相应的字节码文件必须在与包名称相匹配的目录结构中。
7.3 接口与类的区别:
1. 接口不能用于实例化对象。
2. 接口没有构造方法。
3. 接口中所有的方法必须是抽象方法。
4. 接口不能包含成员变量,除了 static 和 final 变量。
5. 接口不是被类继承了,而是要被类实现。
6. 接口支持多继承。
7.4 接口的语法格式:
[可见度] interface 接口名称 [extends 其他的接口名名] {
// 声明变量
// 抽象方法
}
7.5 接口的实现:
当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类。
类使用implements关键字实现接口。在类声明中,Implements关键字放在class声明后面。
语法格式:
[可见度] class 对象名 implements 接口名称[, 其他接口名称, 其他接口名称..., ...] ...
7.6 重写接口中声明的方法时的规则:
1. 类在实现接口的方法时,不能抛出强制性异常,只能在接口中,或者继承接口的抽象类中抛出该强制性异常。
2. 类在重写方法时要保持一致的方法名,并且应该保持相同或者相兼容的返回值类型。
3. 如果实现接口的类是抽象类,那么就没必要实现该接口的方法。
7.7 在实现接口的时候,也要注意一些规则:
1. 一个类可以同时实现多个接口。
2. 一个接口能继承另一个接口,这和类之间的继承比较相似。
实例:
Lesson2.java
package lesson2;
public class Lesson2 {
public static void main(String[] args) {
System.out.println("Lesson2 Class.");
//Students students = new Students("lili", "woman", 22);
//students.showInfo();
Yoyo stu1 = new Yoyo("yoyo", "girl", 22);
System.out.println(stu1.getAge());
stu1.setScore(99.8);
System.out.println(stu1.getScore());
System.out.println(stu1.getName());
System.out.println(stu1.getSex());
stu1.showInfo();
}
}
Students.java
package lesson2;
public abstract class Students
{
private String name;
private int age;
private String sex;
public Students(String name, String sex, int age) {
System.out.println("构造器");
this.name = name;
this.sex = sex;
this.age = age;
}
public String getName() {
return name;
}
public String getSex() {
return sex;
}
public int getAge() {
return age;
}
public void showInfo() {
System.out.println("name is " + name + " age: " + age);
}
}
Yoyo.java
public class Yoyo extends Students implements StudentsScore {
private double score;
public Yoyo(String name, String sex, int age) {
super(name, sex, age);
}
public double getScore() {
System.out.println("get score.");
return score;
}
public void setScore(double score) {
System.out.println("set score");
this.score = score;
}
@Override
public void setScore() {
// TODO Auto-generated method stub
}
}
StudentsScore.java
package lesson2;
public interface StudentsScore {
public double getScore();
public void setScore();
}
输出结果:
Lesson2 Class.
构造器
22
set score
get score.
99.8
yoyo
girl
name is yoyo age: 22
7.8 接口的继承
一个接口能继承另一个接口,和类之间的继承方式比较相似。接口的继承使用extends关键字,子接口继承父接口的方法。
Java中,类的多继承是不合法,但接口允许多继承。
在接口的多继承中extends关键字只需要使用一次,在其后跟着继承接口。
语法格式:
public interface 接口名 extends 接口名2, 接口名3
// 文件名: Sports.java
public interface Sports
{
public void setHomeTeam(String name);
public void setVisitingTeam(String name);
}
// 文件名: Football.java
public interface Football extends Sports
{
public void homeTeamScored(int points);
public void visitingTeamScored(int points);
public void endOfQuarter(int quarter);
}
7.9 标记接口
最常用的继承接口是没有包含任何方法的接口。标记接口是没有任何方法和属性的接口.它仅仅表明它的类属于一个特定的类型,供其他代码来测试允许做一些事情。
标记接口作用:简单形象的说就是给某个对象打个标(盖个戳),使对象拥有某个或某些特权。
1. 建立一个公共的父接口:
正如EventListener接口,这是由几十个其他接口扩展的Java API,你可以使用一个标记接口来建立一组接口的父接口。例如:当一个接口继承了EventListener接口,Java虚拟机(JVM)就知道该接口将要被用于一个事件的代理方案。
2. 向一个类添加数据类型:
这种情况是标记接口最初的目的,实现标记接口的类不需要定义任何接口方法(因为标记接口根本就没有方法),但是该类通过多态性变成一个接口类型。
例如:java.awt.event 包中的 MouseListener 接口继承的 java.util.EventListener 接口定义如下:
package java.util;
public interface EventListener
{}