【java期末速成】面向对象,类,继承和多态

面向对象编程概念

目前的程序设计主要分为两类:一类是面向过程的程序设计,代表性的语言有 C、Fortran
等;另一类是面向对象的程序设计,代表性的语言主要有 Java、C++、C#、Python 等。
向对象程序设计是当前广泛采用的一种程序设计思想和方法,它主要是用类似于人类思维的
模式去理解和解决程序设计中的问题,如将客观世界中的各种事物抽象为对象,每个对象都
拥有自己的状态( 对象的属性 )和行为( 对象的方法 ),各对象之间通过方法或函数的调用
实现通信,最终完成需求任务。
1.对象
每个对象都有自己的属性与行为
2. 类
程序设计中的类是对 现实世界某些对象的共同特征和行为的抽象,所以类可以定义为具有共同属性和行为对象的抽象描述。通常,类被称为模板,对象就是由这些模板产生的。
3.封装
封装是隐藏对象属性和行为细节的一个手段,它隐蔽了类的具体实现功能,使得一个类
在使用其它类中的功能时,不必了解这个类的内部细节是如何实现的,只需明确它所ᨀ 供的
外部接口即可,这种机制为类模块的重复使用和类间的相互调用ᨀ 供了有利条件:当外部要
想使用该类的功能时,只需通过其提供的外部接口就可以使用。
面向对象的程序设计语言ᨀ 供了这种能将对象中的状态数据隐藏起来的机制,称为“封
装”。对于隐藏起来的数据,只有对象自己的方法才能操作,从而保证对象的安全性和完整
性。
4.继承
继承是通过已有的类来创建新类的机制,从而达到代码复用的目的。利用继承,可以先
创建一个拥有公共属性和行为的一般类,再根据该一般类创建具有特殊属性的新类。
5.多态
Java 中提供两种多态的实现机制:方法重载时实现的静态多态和方法覆盖时实现的动态
多态。
静态多态,也称为编译时多态,是由方法重载(Overloading)引起的一种多态形式。方
法重载是指同一个类中的多个方法具有相同的名字,但具有不同的参数列表,不同的参数列表
指的是参数的个数不同或者参数的类型不同。
动态多态,也称为运行时多态,它是通过动态绑定来实现的,是由方法覆盖(方法重写,
Overriding)引起的一种多态形式。方法覆盖是存在于子父类之间的,子类定义的方法与父类
中的方法具有相同的方法名字,相同的参数列表和返回类型,同时子类的访问修饰符高于或
等于父类的访问修饰符。
6.消息
对象是独立又彼此联系的,对象间通过消息传递相互通信,来模拟现实世界中不同实体
间的联系。

类和对象

类定义的基本格式如下:
<类声明>{
        <类主体>
}
Java 类声明的完整语法格式定义如下:
[类修饰符] class 类名 [extends 父类名][implements 接口名列表]
(1) 类修饰符
包含访问控制修饰符(只允许公共修饰符 public 和默认修饰符 default 两种,详见 4.6
访问修饰符)、抽象类修饰符 abstract、最终类修饰符 final。这里,abstract 和 final 不能同时
修饰一个类。
(2) extends 父类名
extends 关键字用来表明创建的类继承的是哪个父类,其后只能有一个父类名。若类的
定义中无 extends,则该类的父类默认为 java.lang.Object 类。
(3) implements 接口名列表
implements 关键字用来表明创建的类实现了哪些接口,其后可以有多个接口名。
类主体的基本格式如下:
<类声明>{
        [成员变量声明;]
        [构造方法声明;]
        [成员方法声明;]
}

 属性+方法

(1)成员变量
成员变量的声明格式为:
[变量修饰符] 类型 变量[=初始值][,变量]
(2)成员方法
成员方法的声明格式为:
[方法修饰符] 方法返回值类型 方法名([参数列表])
{
               [方法体;]
}
(3)构造方法
构造方法要求与类名相同且没有返回值类型。
构造方法的声明格式为:
[访问修饰符] 构造方法名([参数列表])
{
[方法体;]
}
具体含义及特点如下:
(1)构造方法访问修饰符
只能是 public、protected、private 和缺省的访问控制修饰符,不能使用其它修饰符。
(2)构造方法名
构造方法的名称必须与类的名称相同。
(3)参数列表
参数列表中可以有 0 个或多个参数项,相邻的两个参数项之间用逗号间隔,参数类型可
以是基本数据类型,也可以是引用类型。
(4)构造方法的执行
构造方法的功能是创建对象,只能通过 new 运算符访问并执行构造方法;在构造方法
中可以通过 this 引用当前类的构造方法,通过 super 访问父类的构造方法,但必须是构造方
法体中的第一条语句。
注意:构造方法不能有返回值类型,即使是 void 类型也不允许。
构造方法有默认的和自定义的两种
默认的构造方法
当类中没有ᨀ 供任何构造方法时,就会存在一个默认的无参构造方法,该构造方法具有
以下特点:
  •  无形参、方法体中无语句。
  •  功能是创建对象并给对象的成员变量赋约定的值。
  •  构造方法的访问级别取决于类的访问级别。若类的访问级别为 public,则默认构造
方法的访问级别也是 public;若类的访问级别是默认的,则默认构造方法的级别也是默认的。
class Student {
    String name;
    String number;
    String grade;
    String major;
    int age;
    Student(String xm,String xh){ //自定义的构造方法
        name=xm;
        number=xh;
    }
    void study(){ // 行为方法
    System.out.println("姓名:"+name+"[学号"+number+"],正在教室学习");
    }
}

类的使用

1.对象声明
声明对象的格式如下:
类名 对象名;
2.对象创建
创建对象的格式如下:
对象名=new 类名([参数列表]);
new 运算符用于创建一个类的对象并返回该对象的引用,它是为新建对象开辟内存空间的运算符,其中,如果[]中有参数列表的话,那么类定义中就需要有带参数列表的构造方法。
当在程序中创建了某个类的一个对象时,就意味着在内存中开辟了一块存储区,用于保存该对象的属性,这个对象将拥有某个类中定义的全部变量和方法。
3.对象使用
对象的使用可以通过“.”运算符来实现对自己的成员变量和成员方法的调用。要访问或调用 teacher 对象的属性或方法需要首先访问这个对象,然后用运算符“.”连接这个对象的某个属性或方法。
4.对象释放
对象一旦被创建,系统就会为它分配一个内存空间。当对象的使命完成以后,应该将其
从内存中清除,回收对象所占用的内存空间。

this 的使用

1. 用 this 在实例方法和构造方法中引用成员
在类的定义中,如果类的实例方法需要引用本类的实例成员,系统会默认的在实例成员
前加上 this,指向实例成员所属的当前对象。
引用成员的方式如下:
(1)this.变量名:引用本对象的成员变量
(2)this.方法名;引用本对象的成员方法
2. 用 this 区分成员变量和本地变量
3. 用 this 返回实例对象本身
this 可以作为 return 语句的参数,返回当前对象的引用。
4. 用 this 访问本类的构造方法
一个类中可以有多个构造方法。在一个构造方法中可以使用 this 关键词调用类中其他的
构造方法,其调用方式如下:
this([参数列表]);
参数列表可确定访问本类哪个构造方法
注意:由于类方法可以通过类名直接调用,而不是通过对象调用的,因此指代对象实
例本身的 this 关键字不能出现在类方法中。

访问修饰符(必考)

Java 提供了 public(公开的)、protected(受保护的)、缺省和 private(私有的)共 4 种
访问修饰符,它们与 package 包一起构成类的可见性和对象中的属性和方法的可见性,从而
体现 Java 的封装机制。

Java 常用类

Object

Object 类在 Java 里面是一个比较特殊的类,它是所有 Java 类的根类,Java 中所有的其他类都直接或间接地继承 Object 类。在定义一个类时,如果未使用 extends 关键字指明其父类,则默认继承 Object 类,因而,任何 Java 对象都可以使用 Object 类的方法。

2 Object 类的常见方法的使用
1)equals 方法
Object 类中的 equals 方法在默认情况下用来比较两个对象的内存地址是否相同,若相同返回 true,否则返回 false。
equals 和 == 是不一样的。 equals 是比较内容是否相同,而 ==是比较对象的地址是不是相同
 
public class Example6 {
public static void main(String[] args) {
String name1=new String("张三");
String name2=new String("张三");
String name3="张三";
String name4="张三";
System.out.println(name1.equals(name2));//值相等,地址不同
System.out.println(name1.equals(name3));//值相等,地址不同
System.out.println(name3.equals(name4));//值相等,地址相同
System.out.println(name1==name2);//值相等,地址不同
System.out.println(name1==name3);//值相等,地址不同
System.out.println(name3==name4);//值相等,地址相同
}
}

2)toString 方法
返回对象的字符串表示形式。通常,该方法返回一个能表示此对象的字符串,返回值为 String 类型的对象。通常在 Object 的子类中都对该方法进行覆盖。
toString 方法是 Object 类的方法。当我们使用输出语句 System.out.println(对象)打印某个对象的时候,Java 会自动调用对象的 toString 方法。
public class Example7 {
public static void main(String[] args) {
Person p= new Person("张三",20);
    System.out.println(p);
    System.out.println(p.toString());
}
}
class Person {
String name;
int age;
public Person(String s, int x) {
name = s;
age = x;
}
@Override
public String toString() {
return "name:"+name+",age:"+age;
}
}

由上例运行结果看出,程序使用输出语句 System.out.println(对象)打印某个对象的时候,
Java 会自动调用 toString 方法。
3)getClass 方法
public final Class<?> getClass() ;
该方法获取对象的运行时 class 对象,class 对象就是描述对象所属类的对象。

System

System 类也是 java.lang 包中的一个类,该类ᨀ 供了几个系统级的属性和控制方法。由
于该类的构造方法是 private,所以无法创建该类的对象,也就是无法实例化该类。
System 类内部的成员变量和方法都是 static 的,因而使用时直接用 System 类名作为前
缀加上成员变量名与方法名即可。
1、System 类的静态变量
System 中包含了 in、out 和 err 三个成员变量,分别代表标准输入流(键盘输入)、标准输
出流、标准错误输出流。
2、System 类常用的方法
System 类中提供大量的静态方法,可以获取与系统相关的信息或系统级操作,在 System
类的 API 文档中,常用的方法有:
1) public static long currentTimeMillis()
获取系统当前毫秒值。获取当前系统时间与 1970 年 01 月 01 日 00:00 点之前的毫秒差
值,我们可以用它来测试程序的执行时间。
2) public staitc void exit(int status)
终止正在运行的 Java 虚拟机,参数 status 表示状态码,通常用 0 表示正常结束,其它为
异常结束。
3) public static void gc()
运行垃圾回收器。启动 java 虚拟机的垃圾回收器运行,回收内存的垃圾。
public class Example7{
    public static void main(String[] args) {
        long start=System.currentTimeMillis();
        int sum=0;
        for(int i=0;i<=100000;i++){
            sum+=i;
        }
        System.out.println("0~100000 之间整数之和是"+sum);
        long end=System.currentTimeMillis();
        System.out.println("0~100000 之间整数之和是"+sum);
        System.out.println("计算用时"+(end-start)+"毫秒!");
    }
}

Math

(1) Math 类的常量
        Math.E 是 自然对数的底数 ,代表自然数 e,其值为 2.7182818...
        Math.PI 是圆周率, 代表圆周率π,其值为 3.1415926...
(2) Math 类的常用方法
 

Random

日期类和时间类

控制台输入 Scanner

next()和 nextLine()方法比较
  • next()读取字符串内容,只读取到空格为止,不能读取两个有空格或符号隔开的单词,
读取后的光标还是在同一行。
  • nextLine()读取输入的一行字符串,包括单词、单词之间的空格和除回车或换行符等以
外的符号。读取后,会将光标指向下一行。

1) print( ) println( )
  • print() 方法把需要输出的参数以字符串的形式显示在控制台上。此方法在控制台上把
参数打印完后,光标停留在控制台文本的末尾,下一次打印输出就从这里开始。
  • println() 方法也用于在控制台上显示文本。与 print() 不同的是当在控制台上把参数打
印完后,光标自动换行,下一次打印从下一行开始。

2)printf()
printf()提供了一种格式化输出的功能,System.out.printf(format, items)指出按照 format格式输出 items 的值。
在格式符中,还可以指定数据显示所占的位数。如果指定的位数多于数据的位数,通常情况下,输出约定右对齐。如果需要左对齐,可以在格式符中用“-”指定。
public class Example8 {
public static void main(String[] args) {
//变量
int r;
//一级循环
    for(int i=1;i<=9;i++) {
        //二级循环
        for(int j=1;j<=i;j++) {
            System.out.printf("%2d*%-2d=%-3d",i,j,i*j);
        }
        System.out.println();
    }
  }
}

String

1、String 对象的创建

String 对象的创建有两种方法(1) 使用赋值语句把字符串常量赋值给字符串对象,例如:
String s=” student”;
这是比较简化的语法用于创建并初始化 String 对象,其中”student”是表示一个字符串常
量。实际上,java 程序中的字符串常量存放在字符串常量池种,因此,将字符串常量传递给
字符串变量时,只是把字符串的引用赋值给字符串对象 s。
使用 String 的构造方法创建对象。
字符串构造方法有如下 4 个。
无参数的构造方法:
  • public String() //创建一个内容为空的字符串。
  • public String(char[] value) //根据指定字符数组创建对象。
  • public String(String value) //根据指定字符串内容创建对象。
  • public String(StringBuffer value) //根据字符串缓冲区创建对象

注意:new String(); 和 new String("");都是声明一个空串,而不是 null。

2、 String 类的主要方法

1) 获取字符串长度

public int length() 功能描述:获取字符串的长度,其实也就是字符个数

目的主要方法
获取字符串长度
public int length() :获取字符串的长度,其实也就是字符个数
截取一个字符
public char charAt(int index)
该方法返回指定索引处的 char 值,索引范围是从 0~length()-1,ch=”abc”. charAt(1); 结果返回‘b’。
字符串相等比较
public boolean equals (String s)
字符串对象调用 String 类的 equals 方法,比较当前字符串对象是否与参数制定的字符串
s 对 象相同。举例如下。
String s1="Hello";
String s2=new String("Hello"); s1.equals (s2); //true
Java ᨀ 供忽略大小写的字符串相等比较方法,其格式如下。
public boolean equalsIgnoreCase(String anotherString)
将此 String 与 anotherString 进行比较,不考虑大小写。如果两个字符串的长度相等,并且两
个字符串中的相应字符都相等(忽略大小写),则认为这两个字符串是相等的。举例如下。
"hello".equalsIgnoreCase ("Hello");//true
取得子串
public String substring (int beginIndex);//1
public String substring (int beginIndex,int endIndex);//2
substring(int beginIndex)返回一个新的字符串,它是此字符串的一个子字符串。该子字
符串始于指定索引处的字符,一直到此字符串末尾。
substring((int beginIndex,int endIndex)返回一个新字符串,它是此字符串的一个子字符串。
该子字符串从指定的 beginIndex 处开始,一直到索引 endIndex-1 处的字符。因此,该子字符
串的长度为 endIndex-beginIndex。举例如下。
"unhappy'".substring(2);/返回"happy'"
"smiles".substring(1,5);/返回"mile"
字符串连接
public String concat (String str)
该方法将指定字符串联到此字符串的结尾。如果参数字符串的长度为 O,则返回此 String
对象。否则,创建一个新的 String 对象,用来表示由此 String 对象表示的字符序列和由参数
字符串表示的字符序列串联而成的字符序列。举例如下。
"cares".concat ("s"); //返回"caress"
"to".concat("get").concat ("her"); //返回"together"
除此之外,还可以使用“+”运算符实现两个字符串的连接。举例如下。
567+"和 789”;
//返回"567 和 789”
字符串内容比较
public int compareTo(String anotherstring)
按字典顺序比较两个字符串。该比较基于字符串中各个字符的 Unicode 值。将此 String
对象表示的字符序列与参数字符串所表示的字符序列进行比较。如果按字典顺序此 String
对象在参数字符串之前,则比较结果为一个负整数。如果按字典顺序此 String 对象位于参数
字符串之后,则 比较结果为一个正整数。如果这两个字符串相等,则结果为 0。compareTo
只有在方法 equals(Object) 返回 true 时才返回 0。
除此之外,Java ᨀ 供不考虑大小写的字典顺序比较方法。其形式如下。
public int compareToIgnoreCase(String str)
举例如下。
String s1 ="abc";
String s2 ="ABC";
String s3="acb";
String s4 "abc";
System.out.print1n(s1.compareTo(s2));//输出 32
System.out print.1n(s1.compareTo(s3));//输出-1
System.out.println(s1.compareTo(s4));//输出 0
System.out·print1n(s1.compareToIgnoreCase(s2));//输出 0
字符串检索
public int indexof (int ch)
public int indexof (int ch,int fromIndex) public int indexof (String stringName2)
public int indexof (String stringName2,int fromIndex)
字符串检索是指确定一个字符串是否(或从指定位置开始)包含某一个字符或子字符串,
如果包含则返回其位置;如果没有,则返回负数。举例如下。
String s1 ="I love java";
System.out.println(s1.indexof('a'));
//输出 8
System.out println(s1.indexof('j',2)); //输出 7
System.out.print1n(s1.indexof("love");//输出 2
System.out.print1n(s1.index0f("love",9));//输出-1
字符串与字符数组的相互转换
字符数组转换为字符串,其格式如下
public static String copyValueof(char []ch1)
public static String copyValueof (char []ch1,int cBegin,int cCount)
举例如下。
char [ ]ch1={'H','h'};
String s2=String.copyValueof (ch1);//s2=Hh
字符数组转换为字符串,其格式如下
public void getChars (int sBegin,int sEnd,char [ ]ch1,int dBegin)
public char[ ]toCharArray()
举例如下。
String s="this is a demo of the getChars method."
char buf[ ]=new char [20];
s.getChars(10,14,buf,0); //buf 的前 4 个元素为 d e m o
去掉起始和结尾的空格
public String trim()
trim( )返回删除字符串起始和结束的空格后的字符串,如果没有起始和结束空格,则返
回此字符串。举例如下。
String s="this is a demo of the trim method.
String s2=s.trim( ) //s2=this is a demo of the trim method.
字符串替换
public String replace(char oldChar,char newChar)
举例如下。
String s="the war of baronets".replace ('r','y');
字符串大小写转换
将字符串中的大写全部转换为小写,其格式如下。
public String toLowerCase()
举例如下。
String s="I Love Java".toLowerCase () //s="i love java"
将字符串中的小写全部转换为大写,其格式如下。
public String toUpperCase() 举例如下。
String s="I Love Java".toUpperCase()
// s=”I LOVE JAVA”
将其他数据类型转换为字符串
public static String valueof (boolean b)
public static String valueof(char c)
public static String valueof (int i)
public static String valueof (long L)
public static String valueof (float f)
public static String valueof (double d)
举例如下。
String s1=String.valueof (123);
//s1="123"
String s2=String.valueof (true);
//s2="true"
String s3=String.valueof (12.8); //s3="12.8"
另外,Object 类的 toString( )方法,也可实现将其他数据类型转换为字符串。
举例如下。
String s=Double.tostring (12.8);
//s="12.8"
需要注意的是,Object 类的 toString()方法返回以某种方式表示的该对象的字符串,通常
是文本方式,结果应简明、易于读懂,建议所有子类都重写此方法。
字符串分割
public String [ ]split (String regex)
public String [ ]split (String regex,int limit)
根据匹配给定的正则表达式来拆分字符串。此方法返回的数组包含此字符串的每个子字
符串,这些子字符串由另一个匹配给定的表达式的子字符串终止或由字符串结束来终止。数
组中的子字符串按它们在此字符串中的顺序排列。如果表达式不匹配输入的任何部分,则结
果数组只具有一个元素,即此字符串。
String message "I Love Java!";
String[ ]split= message.split (" ")
上例中使用空格分割"I Love Java!"之后,
split[ ]数组包含 3 个元素,分别为 I、Love、
Java!。

字符串的使用例子:

public class Example9{
    public static void main(String[] args) {
        String s="zhongguoshanhai";
        System.out.println("字符串的长度是:"+s.length());//字符串的长度
        System.out.println("获取位置是 1 的字符:"+s.charAt(1));//获取位置是 1 的字符,位置是从 0 开始计算
        System.out.println("获取第一次出现 g 字符的位置:"+s.indexOf('g'));//获取第一次出现 g 字符的位置
        System.out.println("获取从第8位开始截取字符串的内容"+s.substring(8));//获取从第8 位开始截取字符串的内容
        System.out.println("获取从第 5 到第 8 位之间的字符串的内容:"+s.substring(5,8));//获取从第 5 位包含第 5 位,到第 8 位之间的字符串的内容

//创建字符串对象
String s1="helloworld";
String s2=" helloworld ";
String s3=" hello world ";
System.out.println(s1);
System.out.println("s1 去首尾空格后:"+s1.trim());
System.out.println(s2);
System.out.println("s2 去首尾空格后:"+s2.trim());
System.out.println(s3);
System.out.println("s3 去首尾空格后:"+s3.trim());
//创建字符串对象
String s="中国-上海-浦东-陆家嘴";
String[] array=s.split("-");
for(int i=0;i<array.length;i++) {
System.out.println(array[i]);
}
System.out.println(s.replace("陆家嘴","外滩"));
System.out.println("字符串中是否含有浦西?"+s.contains("浦西"));
}
}

StringBuffer

直接看例子

public class Example10 {
    public static void main(String[] args) {
        System.out.println("1、添加方法");
        add();
        System.out.println("2、删除方法");
        remove();
        System.out.println("3、修改方法");
        alter(); 
    }

static void add() {
    StringBuffer sb = new StringBuffer();//定义一个字符串缓冲区
    sb.append("abcdefg");//在末尾添加字符串
    System.out.println("append 添加结果:" + sb);
    sb.insert(3, "123"); //在指定位置插入字符串
    System.out.println("insert 添加结果:" + sb);
}

public static void remove() {
    StringBuffer sb = new StringBuffer("abcdefg");
    sb.delete(1, 5);//指定范围删除
    System.out.println("删除指定位置结果:" + sb);
    sb.deleteCharAt(2);//指定位置删除
    System.out.println("删除指定位置结果:" + sb);
    sb.delete(0, sb.length()); //清空缓冲区
    System.out.println("清空缓冲区结果:" + sb);
}

public static void alter() {
    StringBuffer sb = new StringBuffer("abcdef");
    sb.setCharAt(1, 'p');//修改指定位置字符
    System.out.println("修改指定位置字符结果:" + sb);
    sb.replace(1, 3, "qq"); //替换指定位置字符串或字符
    System.out.println("替换指定位置字符(串)结果:" + sb);
    System.out.println("字符反转结果"+sb.reverse());
}
}

正则表达式

在正则表达式中,\\p{Lower}代表小写字母 a~z,但如果要使元字符代表部分字符,如

代表 a~g 中的一个字母,该如何设置呢?这时可以使用方括号括起来若干个字符来表示一个
元字符,该元字符可代表方括号中的任何一个字符。
例如,regex=“[abc]1”,这样字符串“a1”、“b1”、“c1”都是和正则表达式匹配的字符串。
除此之外还有很多格式。如:
[1234] 代表:1、2、3、4 中任意一个字符。
[^456] 代表:除 4、5、6 之外的任何字符。
[a-g] 代表:a~g 中的任何一个字母。
[a-zA-Z] 可表示任意一个英文字母。
[a-e[m-z]] 代表:a~e,或 m~z 中的任何一个字母(并集运算)。
[a-o&&[def]] 代表:字母 d、e、f 中任意一个字母(交集运算)。
[a-d&&[^bc]] 代表:字母 a、d 中任意一个字母(差运算)。
(ab)|(13)|(50):代表”ab”、”13”、”50”中任意一值。
部分限定符及其含义

继承

继承的定义与访问可见性规则

1. 继承的定义
Java 语言中的继承机制是通过 extends 关键字实现的,其定义格式如下所示。
[类修饰符]class 子类名 [extends 父类名] [implements 接口名列表]
{
        [成员变量的定义及初始化;]
        [成员方法的定义及方法体;]
}
2. 继承的访问可见性规则
(1) 子类与父类处于同一个包
同一个包 p1 中的父类 C1 和子类 C2,父类中非私有的属性和非私有的方法,子类可继
承。私有的属性和私有的方法只属于类本身,不能被子类继承。
2) 子类与父类处于不同包
如果某个包 p1 中的一个类 C2 是 public 修饰的,那么,其它任何一个包中的子类在引入类 C2 所在的包后,父类 C2 中的 public 和 protected 修饰的属性和方法对其它包中的子类都是可继承的。默认和私有的修饰符修饰的属性和方法均不可继承。

成员变量的隐藏与成员方法的覆盖

1. 成员变量的隐藏
class Father{
    int highSpeed=80 ;}
class Son extends Father{
    int highSpeed=100; //隐藏了父类中的成员变量 highSpeed
    public static void main(String [] args){
        Son sf=new Son();
        System.out.println(sf.highSpeed); //输出子类中设定的值 100
    }
}
2. 成员方法的覆盖
class Father{
    String suggest(String Obj,int speed){ //参数中的 Obj 表示车型,speed 代表车速
    return Obj+"可以从左边通行"+"\t 通行速度为"+speed;
    }
}

class Son extends Father{
    String suggest(String x,int y){ //覆盖父类中的成员方法 suggest
    return x+ "可以从右边通行"+"\t 通行速度不超过"+y;
}

public static void main(String [] args){
    Son sf=new Son();
    System.out.println(sf.suggest("小轿车",40)); //输出子类中suggest 方法执行的结果
}
}
注意:子类中方法的访问修饰符只能高于或与父类同级别时,才能实现成员方法的覆
盖。
3.super 关键字的使用
如果子类需要访问被隐藏的父类变量和被覆盖的父类方法时,可以使用 super 关键字。
super 关键字是当前对象的直接父类对象的引用,它指向这个对象的父对象。super 关键字使
用规则如下:
(1) super 关键字只能在非静态方法中使用
(2) super.方法名,访问父类中的方法
(3) super.变量名,访问父类中的变量
(4) super([参数列表])可根据参数列表对应执行父类的构造方法([参数列表])

动态绑定机制

//父类(C)的定义
class C{
    int num=1;
    void show(){
        System.out.println("This is C");
    }
}
//子类(B)的定义
class B extends C{
    int num=2;
    void show(){
        System.out.println("This is B");
    }
}
//子类(A)的定义
class A extends B{
    int num=3;
    void show(){
        System.out.println("This is A");
    }
}
//主类
class Example10{
    public static void main(String[] args){
        C c = new A();
        System.out.println(c.num);
        c.show();
    }
}

类在 main 方法中声明了父类 C 的一个对象 c,但创建并存储的是子类 A 的对象,这种现象也被称为向上转型。
上转型对象有如下操作特点。
(1)上转型对象可以调用父类中被隐藏的成员变量,不能调用子类中新增加的成员变
量和成员方法
(2)上转型对象可以代替子类的对象调用子类中重写的实例方法
(3)上转型对象可以调用子类继承的成员变量
注意:父类创建的对象不能赋值给子类声明的对象。

多态

编译时多态
运行时多态
//父类(Animal)的定义
class Animal{
    void communication(){
        System.out.println("动物都有交流方式");
    }
}
//子类(Bird)的定义
class Bird extends Animal{
    void communication(){
        System.out.println("鸟类通过鸣叫进行交流");
    }
}
//子类(Fish)的定义
class Fish extends Animal{
       void communication(){
            System.out.println("鱼类通过吐泡泡摇尾巴进行交流");
    }
}
//主类
class Example7_8{
    public static void main(String[]args)
    {
    Animal animal;
    animal=new Bird();
    animal.communication();//动态绑定 Bird 类的 communication 方法
    animal=new Fish();
    animal.communication();//动态绑定 Fish 类的 communication 方法
    }
}

抽象类、接口与泛型类

对于面向对象编程来说,抽象是它的一大重要特征。除了类之外, Java 还ᨀ 供了两种
面向对象的抽象:抽象类和接口。

抽象类

抽象方法具体的声明格式为:
abstract <返回值类型> <方法名>(参数列表);
例如,Animal 类的 shout()抽象方法定义如下:
public abstract void shout( ); //叫声的抽象方法

当一个类中包含了抽象方法,该类必须使用 abstract 关键字来修饰,抽象类的具体声明语
法格式为:
abstract class <类名>{
        <类主体>
}
使用 abstract 关键字创建抽象类 Animal 的代码如下。
abstract class Animal {
        //定义成员变量
        public String name ;
        //定义构造方法
        public Animal () {
        }
        //定义抽象方法
        public abstract void shout ();
        public abstract void play ();
}
如果一个类在继承抽象类时,只实现抽象类中的部分抽象方法,则该类仍然是抽象类,
必须用 abstract 修饰。而如果子类实现了抽象类的所有方法,该类就是一个完整实现的类。
下面的代码中,Dog 类实现了 Animal 类的所有抽象方法,Dog 类就变成了一个具体的类。
class Dog extends Animal {
@Override
        public void shout () {
                System . out .println( "I can say 旺旺" ); // 子类给出具体实现
        }
@Override
        public void play () {
                System . out .println( "为主人看家" ); // 子类给出具体实现
        }
}
public class Example11  {
        public static void main ( String [] args) {
                Dog d = new Dog();
                d .shout();
        }
}
abstract class Animal {
        //定义成员变量
        public String name ;
        //定义构造方法
        public Animal () {
                name = "" ;
        }
        public Animal ( String t) {
                name =t;
        }
        //定义抽象方法
        public abstract void shout ();
        public abstract void play ();
}
// 定义 Dog 继承抽象类 Animal
class Dog extends Animal {
        public Dog (){
                super ();
        }
        public Dog ( String t){
                super (t);
        }
        //子类实现父类 Animal 的抽象方法
        public void shout () {
                System . out .println( "狗狗发出的叫声,汪汪" );
        }
        public void play (){
                System . out .println( name + "为主人看家" ); // 子类给出具体实现
        }}
        //定义抽象类 Cat 继承抽象类 Animal
abstract class Cat extends Animal {
        public Cat (){
                super ();
        }
        public Cat ( String t){
                super (t);
        }
        public void play (){
                System . out .println( name + "逮老鼠" ); // 子类给出具体实现
        }
}
抽象类 Animal 有两个抽象方法,Dog 与 Cat 都继承了 Animal 类。由
于 Dog 给出了两个抽象方法的具体实现,因而 Dog 类就成为了一个具体的类。由于 Cat 类
只给出了 play()方法的实现,shout()仍然是抽象方法,因而 Cat 类前面必须加 abstract,予以
修饰。

抽象类总结:
(1) 任何一个类,只要加了 abstract 修饰符,该类就是抽象类
(2) 如果类中有抽象方法,则该类必须用 abstract 修饰符
(3) 抽象类不能被实例化,不能使用 new 关键字为该类创建对象
(4) 抽象类中可以有自己的构造方法,但这些构造方法需要通过子类去调用
(5) 如果子类没有实现父类的所有的抽象方法,则该子类也必须定义为抽象类
(6) abstract 和 final 不能共同修饰类,两者是对立关系

接口

Java 接口是只有常量属性与抽象方法的抽象类。Java 接口的定义方式与类基本相似,
不过接口定义使用的关键字是 interface,接口定义的语法格式如下:
<修饰符> interface <接口名称> [extends <父接口名列表>]{
        //接口体,包含常量和抽象方法
}
语法的说明如下:
(1) 接口修饰符:接口修饰符定义接口的访问权限,有 public 与默认两种选择。
public 表 示该接口可以被任意类访问。
当没有修饰符时,则使用默认的修饰符,此时该接口的访问权限仅局限于接口所属的包。
(2) Interface:定义接口的关键字,相当于类定义中的 class。
(3) <接口名称>:接口名称只要是合法的标识符即可,通常与类名采用相同的命名规
则。
(4) extends: 表示接口的继承关系。 [extends <父接口名列表>]是可选部分,如果没
有继承父接口,就不选。
(5) 父接口名列表:一个接口可以继承多个接口,可以通过关键字 extends 实现, 父接口名列表给出了要继承的接口名称,当有多个父类接口时,用“,”分隔。
(6) 接口体:接口体中含有所需要说明的静态属性和抽象方法。由于接口体中属性只允
许常量,为了使代码更加简洁,属性声明的时候,常量修饰符 static 和 final 全都
省略,且在声明时就给出初始值,该常量值在接口被继承时不能修改。由于接口中
的方法都是抽象方法,方法前的 abstract 修饰也可以省略不写,方法的访问权限通
常设置为 public。
当接口继承多个父接口时,就要 extends 表示继承关系。接口继承允许多继承,这一点
与类不同。在接口多继承时,会出现方法名重名与常量重名的情况,例如:
interface A extends B, C{
        常量定义;
        方法定义;
}
这条语句表示接口 A 继承了接口 B 与 C 所有的常量属性与方法,而且可以再增加自己
的常量与方法。在这个接口继承过程中可能会出现以下情况:
(1)方法重名
如 B 与 C 中有两个方法完全一样,只保留一个。如果两个方法有不同的参数(不同
的类型或参数个数),那么两个方法被重载。若两个方法仅在返回值上不同,则出现错误。
(2)常量重名
两个重名常量全部保留,并使用原来的接口名作为前缀。

接口与抽象类的区别
可以看出,抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。抽象类
是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。设
计层面不同,抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,
它是一种辐射式设计。抽象类是一个类,而接口不是类。

内部类与匿名类

内部类

内部类与类中的成员变量和成员方法一样,均为外部类的成员,其使用有如下特点。
(1) 内部类使用外部类的属性与方法
在内部类中,可以使用外部类的成员变量与方法,内部类可以直 接使用外部
类中的成员变量和方法,即使它们是 private 的,这也是内部类的一个好处。因此不需
要将外部类的对象传递给内部类的构造函数,内部类可以使程序变得简单和简洁。
匿名类
public class Example12  {
        public static void main ( String [] args) {
                Teacher t = new Teacher();
                Student s = new Student () {
                @Override
                void speak () {
                        System . out .println( "这是匿名类体的方法" );
                }        
                }; // 匿名类体
        t .look( s );
        }
}
abstract class Student {
        abstract void speak ();
        }
class Teacher {
        void look ( Student s){
        s.speak();
        }
}

泛型类声明

泛型类的语法格式如下。
修饰符 class 类名称<泛型标识 1,泛型标识 2…>{
        类体
}
public class Example12  {
        public static void main ( String [] args) {
                Circle circle = new Circle( 10 );
                Cone < Circle > circleCone = new Cone< Circle >( circle );
                circleCone . height = 10 ;
                System . out .print( "圆锥体的" );
                circleCone .computeVolume();
                Rectangle rectangle = new Rectangle( 10 , 5 );
                Cone < Rectangle > rectangleCone = new Cone< Rectangle >( rectangle );
                rectangleCone . height = 30 ;
                System . out .print( "矩形锥体的" );
                rectangleCone .computeVolume();
                Triangle triangle = new Triangle( 5 , 10 );
                Cone < Triangle > triangleCone = new Cone< Triangle >( triangle );
                triangleCone . height = 20 ;
                System . out .print( "三角锥体的" );
                triangleCone .computeVolume();
        }
}
// 锥型类
class Cone < E >{
        E bottom_area ;
        double height ;
        public Cone ( E b){
                bottom_area =b;
        }
        public void computeVolume (){
                String s = bottom_area .toString();
                double area = Double . parseDouble ( s );
                System . out .println( "体积是:" + 1.0 / 3.0 * area * height );
        }
}
// 圆形类
class Circle {
        double area , radius ;
        Circle ( double r){
                radius =r;
        }
        public String toString (){
                area = radius * radius * Math . PI ;
                return "" + area ;
        }
}
// 长方形类
class Rectangle {
        double sideA , sideB , area ;
        Rectangle ( double sideA, double sideB){
                this . sideA =sideA;
                this . sideB =sideB;
        }
        public String toString (){
                area = sideA * sideB ;
                return "" + area ;
        }
}
// 三角形类
class Triangle {
        double bottom , height , area ;
        public Triangle ( double bottom, double height) {
                this . bottom = bottom;
                this . height = height;
        }
        @Override
        public String toString () {
                area = 1.0 / 2.0 * bottom * height ;
                return "" + area ;
        }
}
泛型接口
与泛型类的定义类似,Java 也ᨀ 供了泛型接口的实现机制。泛型接口的语法格式:
interface 泛型接口名<泛型列表>{
        接口体
}
public class Example13 {
        public static void main ( String [] args) {
                Language < Dog > lan1 = new Language< Dog >();
                Language < Cat > lan2 = new Language< Cat >();
                lan1 .shout( new Dog());
                lan2 .shout( new Cat());
        }
}
class Language < T > implements Animal < T > {
        public void shout ( T t) {
                System . out .println(t.toString());
        }
}
interface Animal < T > {
        public void shout ( T t);
}
class Dog {
        String speech ;
        Dog (){
                speech = "我使用汪星语" ;
        }
        public String toString (){
                return speech ;
        }
}
class Cat {
        String speech ;
        Cat (){
                speech = "我使用喵星语" ;
        }
        public String toString (){
                return speech ;
        }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值