第二节:面向对象
Posted 位永光
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第二节:面向对象相关的知识,希望对你有一定的参考价值。
1. 类与对象
- 类:类是一个模板,它描述一类对象的行为和状态
- 对象:对象是类的一个实例,有状态和行为
1.1 源文件声明规则
- 一个源文件中只能有一个
public
类 - 一个源文件可以有多个非
public
类 - 源文件的名称应该和
public
类的类名保持一致 - 如果一个类定义在某个包中,那么
package
语句应该在源文件的首行\' - 如果源文件包含
import
语句,那么应该放在package语句和类定义之间。如果没有package
语句,那么import
语句应该在源文件中最前面 import
语句和package
语句对源文件中定义的所有类都有效。在同一源文件中,不能给不同的类不同的包声明
1.2 Import
语句
Import
语句就是用来提供一个合理的路径,使得编译器可以找到某个类(或者说导入某个类)
import java.io.*; /* 导入io下所有类 */
import java.io.BufferedReader; /* 导入io下 BufferedReader 类 */
1.3 Java
类
命令规则
类的第一个字母大写
类成员
一个类可以包含以下类型变量:
- 局部变量:在方法、构造方法或者语句块中定义的变量被称为局部变量。变量声明和初始化都是在方法中,方法结束后,变量就会自动销毁
- 成员变量:成员变量是定义在类中,方法体之外的变量。这种变量在创建对象的时候实例化。成员变量可以被类中方法、构造方法和特定类的语句块访问
- 类变量:类变量也声明在类中,方法体之外,但必须声明为
static
类型
构造方法
每个类都有构造方法。如果没有显式地为类定义构造方法,Java编译器将会为该类提供一个默认构造方法
public class Puppy{
public Puppy(){
}
public Puppy(String name){
// 这个构造器仅有一个参数:name
}
}
初始化静态对象
Java
中static
代码块用于初始化静态对象
public class Util{
private static String admin = null;
static {
admin = "管理员";
}
}
1.4 Java
对象
对象是根据类创建的。在Java中,使用关键字new
来创建一个新的对象
创建对象需要以下三步:
- 声明:声明一个对象,包括对象名称和对象类型
- 实例化:使用关键字
new
来创建一个对象 - 初始化:使用
new
创建对象时,会调用构造方法初始化对象
2. Java
抽象类/方法
2.1 抽象类
如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类
抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样,由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用
语法格式:使用
abstract class
来定义抽象类
public abstract class Employee{
...
}
2.2 抽象方法
类包含一个特别的成员方法,该方法的具体实现由它的子类确定,那么可以在父类中声明该方法为抽象方法
- 如果一个类包含抽象方法,那么该类必须是抽象类
- 任何子类必须重写父类的抽象方法,或者声明自身为抽象类
- 构造方法,类方法(用
static
修饰的方法)不能声明为抽象方法
语法格式
Abstract
关键字同样可以用来声明抽象方法,抽象方法没有定义,方法名后面直接跟一个分号,而不是花括号
public abstract class Employee{
...
public abstract double computePay();
}
3. Java
继承
一个类只能继承一个抽象类,而一个类却可以实现多个接口
3.1 继承类
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为;所有的类都是继承于 java.lang.Object
语法格式:通过
extends
关键字
class 父类 {
}
class 子类 extends 父类 {
}
继承的特性
- 子类拥有父类非private的属性,方法
- 子类可以拥有自己的属性和方法
- 子类可以用自己的方式实现父类的方法
Java
的继承是单继承,但是可以间接多重继承(A类继承B类,B类继承C类)
3.2 实现接口
使用 implements
关键字可以变相的使java
具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔)
语法格式:通过
implements
关键字
public interface A {
public void eat();
public void sleep();
}
public interface B {
public void show();
}
public class C implements A,B {
}
3.3 super
关键字
通过super
关键字来实现对父类成员的访问,用来引用当前对象的父类
class Animal {
void eat() {
System.out.println("animal : eat");
}
}
class Dog extends Animal {
void eat() {
System.out.println("dog : eat");
}
void eatTest() {
this.eat(); // this 调用自己的方法
super.eat(); // super 调用父类方法
}
}
构造器
如果父类的构造器带有参数的,则必须在子类的构造器中显式地通过super
关键字调用父类的构造器并配以适当的参数列表,如果父类有无参构造器,则在子类的构造器中用super调用父类构造器不是必须的
class SuperClass {
private int n;
SuperClass(){
System.out.println("SuperClass()");
}
SuperClass(int n) {
System.out.println("SuperClass(int n)");
this.n = n;
}
}
class SubClass extends SuperClass{
SubClass(){
super(300); // 调用父类有参构造函数,并显式传入参数
System.out.println("SubClass");
}
}
3.4 final
关键字
声明类可以把类定义为不能继承的,即最终类;或者用于修饰方法,该方法不能被子类重写
- 实例变量也可以被定义为
final
,被定义为final
的变量不能被修改 final
类中的方法自动地声明为final
,但实例变量并不是
声明类
final class 类名 {
...
}
声明方法
修饰符(public/private/default/protected) final 返回值类型 方法名(){
...
}
4. Java
多态
4.1 重写(Override
)
重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变
方法的重写规则
- 参数列表必须完全与被重写方法的相同
- 返回类型必须完全与被重写方法的返回类型相同
- 访问权限不能比父类中被重写的方法的访问权限更低
- 父类的成员方法只能被它的子类重写
- 声明为
final
的方法不能被重写 - 声明为
static
的方法不能被重写,但是能够被再次声明 - 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为
private
和final
的方法 - 子类和父类不在同一个包中,那么子类只能够重写父类的声明为
public
和protected
的非final
方法 - 构造方法不能被重写
class Animal{
public void move(){
System.out.println("动物可以移动");
}
}
class Dog extends Animal{
public void move(){
System.out.println("狗可以跑和走");
}
}
4.2 重载(Overload
)
重载是在一个类里面,方法名字相同,而参数不同,返回类型可以相同也可以不同
每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表
重载规则
- 被重载的方法必须改变参数列表(参数个数或类型或顺序不一样)
- 被重载的方法可以改变返回类型
- 被重载的方法可以改变访问修饰符
- 被重载的方法可以声明新的或更广的检查异常
- 方法能够在同一个类中或者在一个子类中被重载
4.3 重写与重载之间的区别
区别点 | 重载方法 | 重写方法 |
---|---|---|
参数列表 | 必须修改 | 一定不能修改 |
返回类型 | 可以修改 | 一定不能修改 |
异常 | 可以修改 | 可以减少或删除,一定不能抛出新的或者更广的异常 |
访问 | 可以修改 | 一定不能做更严格的限制(可以降低限制) |
4.4 多态
多态就是同一个接口,使用不同的实例而执行不同操作
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法
多态的实现方式
-
方式一:重写
-
方式二:接口
-
方式三:抽象类和抽象方法
5. Java
接口
接口特性
-
接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为
public abstract
-
接口中可以含有变量,但是接口中的变量会被隐式的指定为
public static final
变量 -
接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法
接口声明
[可见度] interface 接口名称 [extends 其他的类名] {
// 声明变量
// 抽象方法
}
实现接口
-
当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类
-
类使用
implements
关键字实现接口且放在class
声明后面
...implements 接口名称[, 其他接口名称, 其他接口名称..., ...] ...
简单示例
interface Animal {
public void eat();
public void travel();
}
public class MammalInt implements Animal{
public void eat(){
System.out.println("Mammal eats");
}
public void travel(){
System.out.println("Mammal travels");
}
public int noOfLegs(){
return 0;
}
}
接口的继承
一个接口使用extends
关键字能继承另一个接口,子接口继承父接口的方法(多个接口用逗号隔开)
语法格式
public interface 接口 extends 接口1, 接口2
简单示例
// 文件名: 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);
}
6. Java
枚举
Java
枚举是一个特殊的类,一般表示一组常量,使用 enum
关键字来定义,各个常量使用逗号 , 来分割
6.1 常量枚举
public enum Color {
RED, GREEN, BLANK, YELLOW
}
6.2 特殊常量枚举
public enum test {
ERROR(500,"错误"),
SUCCESS(200,"成功");
test(int code, String msg) {
this.code = code;
this.msg = msg;
}
private int code;
private String msg;
// get,set
}
7. Java
包装类
Java
中每一种基本类型都会对应一个唯一的包装类,基本类型与其包装类都可以通过包装类中的静态或者成员方法进行转换。每种基本类型及其包装类的对应关系如下,值得注意的是,所有的包装类都是final
修饰的
基本数据类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
7.1 包装类与基本类型的转换
从源代码的角度来看,基础类型和包装类型都可以通过赋值语法赋值给对立的变量类型,如下面的代码所示:
Integer a = 1;
int a = new Integer(1);
首先,生成一个常量1,然后调用Integer.valueOf(int)
方法返回Integer
对象,最后将对象的地址(引用)赋值给变量a
。Integer a = 1;
其实相当于Integer a = Integer.valueOf(1);
下表是所有包装类中的类型转换方法:
包装类 | 包装类转基本类型 | 基本类型转包装类 |
---|---|---|
Byte | Byte.valueOf(byte) | byteInstance.byteValue() |
Short | Short.valueOf(short) | shortInstance.shortValue() |
Integer | Integer.valueOf(int) | integerInstance.intValue() |
Long | Long.valueOf(long) | longInstance.longValue() |
Float | Float.valueOf(float) | floatInstance.floatValue() |
Double | Double.valueOf(double) | doubleInstance.doubleValue() |
Character | Character.valueOf(char) | charInstance.charValue() |
Boolean | Boolean.valueOf(booleann) | booleanInstance.booleanValue() |
7.2 装箱与拆箱
-
装箱操作:将基本数据类型变为包装类的形式
每个包装类的构造方法都可以接收各自数据类型的变量
-
拆箱操作:从包装类之中取出被包装的数据
利用
Number
类中提供的一系列的:xxxValue()
方法完成
代码示例:
public class TestDemo {
public static void main(String args[]) {
Integer obj = new Integer(10); // 将基本数据类型装箱
int temp = obj.intValue(); // 将基本数据类型拆箱
System.out.println(temp * 2); // 结果为20
}
}
字符串与基本数据类型的互相转换:
- 字符串变为基本数据类型,依靠包装类的
parseXxx()
方法 - 基本数据类型变为字符串,依靠
String.valueOf(数据类型 变量)
方法
以上是关于第二节:面向对象的主要内容,如果未能解决你的问题,请参考以下文章