目录
第三章 面向对象(上)
3.1 面向对象的概念
1.封装性
2.继承性
3.多态性
3.2 类与对象
1.类的定义
2.对象的创建与使用
3.类的设计
4.类的封装
案例篇:超市购物程序设计
3.3 构造方法
1.构造方法的定义
2.构造方法的重载
3.4 this关键字
3.5 垃圾回收
3.6 static关键字
静态变量
静态方法
静态代码块
3.7 成员内部类
成员内部类
案例篇:银行新用户现金业务办理
第四章 面向对象(下)
4.1 类的继承
继承的概念
重写父类方法
super关键字
4.2 final关键字
4.3 抽象类和接口
抽象类
接口
案例篇:USB接口程序设计
4.4 多态
多态概念
多态的类型转换
Object类
匿名内部类
案例篇:模拟物流快递系统程序设计
封装性是面向对象的核心思想,将对象的属性和行为封装起来,不需要让外界知道具体实现细节,这就是封装思想。例如:用户使用电脑,只需要敲键盘就可以了,无需知道电脑内部是如何工作的,即使用户可能碰巧知道电脑工作原理,但在使用时,并不完全依赖电脑工作原理这些细节。
继承性主要描述的是类与类之间的关系,通过继承,可以在无需重写编写原有类的情况下,对原有类的功能进行扩展。
继承不仅增强了代码的复用性、提高开发效率,而且也减少了代码的重复性,还为程序的维护补充提供了便利。
类是对某一事物的抽象描述,而对象用于表示显示中国该类事物的个体。
在面向对象的思想中最核心的就是对象,为了在程序中创建对象,首先需要定义一个类。类是对象的抽象,它用于描述一组对象的共同特征和行为。类中可以定义成员变量和成员方法,其中成员变量用于描述对象的特征,也被称作属性,成员方法用于描述对象的行为,可简称为方法。
案例:
/*
* 描述人事物
* 都是人的共性内容
*/
public class Dc {
int age = 10; //定义int类型变量age
//定义speak()方法
public void speak() {
int age = 60;
System.out.println("大家好,我今年" + age +"岁!");
}
}
class Person{
int age = 10; //类中定义的变量被称作成员变量
void speak() {
int age = 60; //方法内部定义的变量被称作局部变量
System.out.println(“大家好,我今年“+age+”岁!”);
}
}
类名 对象名称 = new 类名();
Person p = new Person();
public class Student {
String name; //定义一个姓名属性
int age; //定义一个年龄属性
public void introduce() {
//方法中打印属性name和age的值
System.out.println("大家好,我叫" + name+ ",我今年" + age + "岁!");
}
}
案例:
class Student{
private String name;//将name属性私有化
private int age;//将age属性私有化
//下面的共有的方法间接访问类中的属性getXX方法,setXXX方法
public String getName() {
return name;
}
public void setName(String stuName) {
name=stuName;
}
public int getAge() {
return age;
}
public void setAge(int stuAge) {
//下面是对传入的参数进行检查
if(stuAge<0) {
System.out.print("对不起,您输入的年龄不合法...");
}else {
age=stuAge;
}
}
public void introduce() {
System.out.println("大家好,我叫"+name+",我今年"+age+"岁");
}
}
public class Hello {
public static void main(String[] args) {
Student sut=new Student();
Student stu;
stu.setAge(-30);
stu.setName("韩强");
stu.introduce();
}
}
/*商品类
* 描述商品这个事物
*/
public class Demo6{
private String proName;//商品名
public String getproName() {
return proName;
}
public void setproName(String proName) {
this.proName=proName;
}
}
/*
* 定义超市类
* 描述超市事物
* 超市名字
* 超市的仓库,存储商品
* 售货方法
*/
public class Market {
private String marketName;//超市名字
private Demo6[] productArr;//仓库,存储商品,里面存储若干商品
public String getMarketName() {
return marketName;
}
public void setMarketName( String marketName) {
this.marketName=marketName;
}
public Demo6[] getProductArr() {
return productArr;
}
public void setproductArr(Demo6[] productArr) {
this.productArr=productArr;
}
public Demo6 sell(String name) {//卖货,指定商品名字
for(int i=0;i
/*
* 定义人类
* 描述人这个事物
* 人的名字
* 购物功能
*/
public class Person{
private String name;//人名
public String getName() {
return name;
}
public void setNme(String name) {
this.name=name;
}
public Demo6 shopping(Market market,String name) {//购物,指定去哪个超市,商品名
return market.sell(name);//调用超市的卖货方法,指定商品名字,把卖出去的或的结果返回
}
}
public class Shopping {
public static void main(String[] args) {
//创建商品对象,给商品名字赋值
Demo6 p1=new Demo6();
Demo6 p2=new Demo6();
Demo6 p3=new Demo6();
Demo6 p4=new Demo6();
Demo6 p5=new Demo6();
p1.setproName("电视机");
p2.setproName("洗衣机");
p3.setproName("豆浆机");
p4.setproName("空调机");
p5.setproName("吹风机");
//创建超市对象,给超市名字赋值,给仓库赋值
Market m=new Market();
m.setMarketName("家乐福");
m.setproductArr(new Demo6[] {p1,p2,p3,p4,p5});
//创建购物者,给名字赋值
Person p=new Person();
p.setNme("小韩");
//调用购物者的购物方法,指定超市商品,得到结果
Demo6 result=p.shopping(m, "豆浆机");
//根据结果进行判断
if(result!=null) {
System.out.println(p.getName()+"在"+m.getMarketName()+"买到了"+result.getproName());
}else {
System.out.println(p.getName()+"白跑一趟,在"+m.getMarketName()+"什么没买到");
}
}
}
运行结果:
在一个类中定义的方法如果同时满足以下三个条件,该方法称为构造方法,具体如下:
与普调方法一样,构造方法也可以重载,在一个类中可以定又多小构遗方法,只要每个构造方法的参数类型或参数个数不同即可。在创建对象时,可以运过调用不同的构造方法来为不同的属性进行就值。
例如都声明为age。但是这样做又会导致成员变量 和局部变量 的名称冲突,在方法中将无法访问成员变量age。为了解决这个问题,Java中提供了一个关键字this来指代当前对象,用于在方法中访问对象的其他成员。this的作用就是区分成员变量和局部变量的同名情况。
在定义一个类时,只是在描述某类事物的特征和行为,并没有产生具体的数据。只是通过new关键字创建该类的实例对象后,系统才会为每个对象分配空间,存储各自的数据。有时候,开发人员会希望某些特定的数据在内存中只有一份,而且能够被一个类的所有实例对象所共享。例如某个学校所有学生共享同一个学校名称,此时完全不必在每个学生对象所占用的内存空间中都定义一个变量来表示学校名称,而可以在对象以外的空间定义一个表示学校名称的变量,让所有对象来共享。
案例:
package Package1;
/*
* 静态变量
*/
class Student{
static String schoolName; //定义静态变量schoolName
}
public class Test1 {
public static void main(String[] arge)throws Exception{
Student stu1 = new Student(); //创建学生对象
Student stu2 = new Student(); //创建学生对象
//静态成员的调用方式,类名,对象
Student.schoolName = "传智博客"; //为静态变量赋值
System.out.println("我的学校是:"+stu1.schoolName); //打印第一个学生对象的学校名
System.out.println("我的学校是:"+stu2.schoolName); //打印第一个学生对象的学校名
}
}
运行结果:
案例:
package Package1;
/*
* 静态方法的使用
*/
class Person{
public static void sayHello() { //定义静态方法
System.out.println("hello");
}
}
public class Test1 {
public static void main(String[] arge)throws Exception{
//1 类名。方法的方式调用方法
Person.sayHello();
//2 实例化对象的方式调用静态方法
Person p = new Person();
p.sayHello();
}
}
在Java类中,使用一对大括号包围起来的若干行代码被称为一个代码块,用static关键字修饰的代码块称为静态代码块。当类被加载时,静态代码块会执行由于类只加载一次,因此静态代码块只执行一次。在程序中,通常会使用静态代码块来对类的成员变量进行初始化。
案例:
package Package1;
/*
* 静态代码块
*/
class Person{
//静态代码块
static {
System.out.println("Person类中的静态代码块执行了");
}
}
public class Test1{
//静态代码块
static {
System.out.println("测试类中的静态代码块执行了");
}
public static void main(String[] args) throws Exception{
//下面代码创建两个Person对象
Person p1 = new Person();
Person p2 = new Person();
}
}
运行结果:
外部类名.内部类名 变量名 = new 外部类名 ().new 内部类名();
/*
* 定义银行类
* 属性:银行名称,储户名称,密码,余额,交易额度
* 功能:开门营业,存钱,取钱,关门
*/
public class Tas {
static String bankName;//定义静态变量银行名字
private String name;//储户姓名
private String password;//密码
private double balance;//账户余额
private double turnover;//交易额
//静态方法,打出银行的欢迎语句
public static void welcome() {
System.out.println("欢迎来到"+bankName+"------------");
}
public Bank(String name,String password,double balance,double turnover) {
super();
this.name = name;
this.password = password;
this.balance = turnover;
this.turnover = turnover-10;
System.out.println(name+"开户成功,账户余额"+balance);
}
//存款功能
public void deposit(double turnover) {
balance=balance+turnover;
System.out.println(name+"您好,你的账户已经存入"+turnover+"元"+"当前余额"+balance+"元");
}
//取款功能
public void withdrawal(String password,double turnover) {
//根据传入的变量与成员变量对比,判断密码是否正确
if(this.password!=password) {
System.out.println("您输入的密码错误");
return;
}
//判断余额是否充足
if(balance-turnover>0) {
balance=balance-turnover;
System.out.println(name+"您好,您的账户已取出"+turnover+"元,当前余额"+balance+"元");
}else {
System.out.println("对不起,账户余额不足");
}
}
//静态方法,打印出银行欢迎下次光临
static void welcomeNext() {
System.out.println("请携带好随身财物,欢迎下次光临"+bankName+"----------------");
}
}
public class Demo6{
public static void main(String[] args) {
//定义一家银行,给静态变量(银行名字)赋值,类名.调用成员变量
Bank.bankName="招商银行";
//银行的打印欢迎光临语句,调用静态方法
Bank.welcome();
//开户操作通过调用构造方法进行开户
Bank bank=new Bank("小梦","654321",100, 0);
//进行存款操作
bank.deposit(500);
//取款时密码输入错误,取款失败
bank.withdrawal("123456",200);
//取款时余额不足,取款失败
bank.withdrawal("654321",1000);
//取款时密码正确,余额充足,取款成功
bank.withdrawal("654321",200);
//银行打印到别语句,调用静态方法
Bank.welcomeNext();
}
}
运行结果:
在类的继承中,需要注意一些问题,具体如下:
class A{}
class B{}
class C extends A,B{} //C类不可以同时继承A类和B类
class A{}
class B extends A{}
class C extends A{} //类B和类C都可以继承类A
class A{}
class B extends A{} //类B继承类A,类B是类A的子类
class C extends B{} //类C继承类B,类C是类B的子类,同时也是类A的子类
在继承关系中,子类会自动继承父类中定义的方法,但有时在子类中下需要对继承的方法进行一些修改,即对父类的方法进行重写。需要注意的是,在子类中重写的方法需要和父类重写的方法具有相同的方法名、参数列表以及返回值类型。方法重写是对父类功能的一些改进,同时也是对父类功能的扩展,而也是多态的一个非常重要的前提就是方法的重写。
子类重写父类要保证子类方法的权限必须大于或者等于父类方法权限,否则将会报错
当子类重写父类的方法后,子类对象将无法访问父类被重写的方法,为了解决这个问题,在Java中专门提供了一个 super关键字用于访问父类的成员,可以访问父类的成员变量,成员方法和构造方法.
1、使用super关键字访问父类成员变量和成员方法,格式:
super.成员变量
super.成员方法([参数1,参数2...])
案例:
/*
* super关键字
* 子类中,访问父类的成员
* 父类成员变量,和父类的成员方法
*/
//定义Animal作为父类
class Animal{
String name="+动物";
//定义动物叫的方法
public void shout() {
System.out.println("动物发出叫声");
}
}
//定义Dog类继承Animal父类
class Dog extends Animal{
String name="犬类";
//重写父类的方法shout
public void shout() {
//访问父类的方法shout()
//super.父类方法()
super.shout();
}
//定义打印机name属性的方法
public void printName() {
System.out.println("name"+super.name);//访问父类的成员变量name
}
}
public class Hello {
public static void main(String[] args) {
Dog dog=new Dog();//创建Dog类对象,子类对象
dog.shout();//调用Dog类中的方法about
dog.printName();//调用Dog类的方法printName
}
}
运行结果:
2、使用super关键字访问父类的构造方法,格式:
super([参数1,参数2...])
案例:
/*
* super()访问父类的构造方法
*/
//定义一个Animal类作为父类
class Animal{
public Animal() {
System.out.println("我是一只动物");
}
public Animal(String name) {
System.out.println("我是一只"+name);
}
}
//定义Dog类继承父类
class Dog extends Animal{
public Dog() {
System.out.println("沙皮狗");
}
}
//定义测试类
public class Hello {
public static void main(String[] args) {
Dog dog=new Dog();//创建Dog类的对象,子类对象
}
}
运行结果:
必须是子类构造方法,才能调用父类构造方法
final关键词可用于修饰类、变量和方法,它有“无法改变”或者“最终”的含义,因此被final修饰的类、变量和方法键具有以下特性:
- final修饰的类不能被继承
- final修饰的方法不能被子类重写
- final修饰的变量(成员变量和局部变量)是常量,只能赋值一次
abstract void shout(); //定义抽象方法shout()
[public] interface 接口名 [extends 接口1,接口2...]{
[public] [static] [final] 数据类型 常量名 = 常量值;
[public] [abstract] 返回值 抽象方法名(参数列表);
}
[修饰符] class <类名> [extends <超类名>] [implements <接口1> ,<接口2>,......]
package cn.itcast.chapter04.task01;
public class computer {
private USB[]usbArr=new USB[4];
public void add(USB usb) {
for(int i=0;i
package cn.itcast.chapter04.task01;
import static java.lang.System.out;
public class KeyBoard implements USB{
public void turnon() {
out.println("键盘启动了");
}
public void turnoff() {
out.println("键盘关闭了");
}
}
package cn.itcast.chapter04.task01;
public class Mic implements USB {
public void turnon() {
System.out.println("麦克风启动了");
}
public void turnoff() {
System.out.println("麦克风关闭了");
}
}
package cn.itcast.chapter04.task01;
public class Mouse implements USB {
public void turnon() {
System.out.println("鼠标启动了");
}
public void turnoff() {
System.out.println("鼠标关闭了");
}
}
package cn.itcast.chapter04.task01;
public class Task01Taxt {
public static void main(String[]args) {
computer c=new computer();
c.add(new Mouse());
c.add(new Mic());
c.add(new KeyBoard());
c.poweron();
System.out.println();
c.poweroff();
System.out.println();
}
}
package cn.itcast.chapter04.task01;
public interface USB {
public void turnon();
public void turnoff();
}
运行结果:
案例:
package Package1;
/*
* 对象的多态性
* 父类或者是接口引用 = new 子类的对象
*/
//定义接口Animal
interface Animal{
public static void shout() {
// TODO Auto-generated method stub
} //定义抽象方法
}
//定义Cat类实现Animal接口
class Cat implements Animal{
//实现shout方法
public void shout() {
System.out.println("喵喵...");
}
}
//定义Dog类实现Animal接口
class Dag implements Animal{
//实现shout方法
public void shout() {
System.out.println("汪汪...");
}
}
//定义测试类,多态
public class Test1{
public static void main(String[] args) throws Exception{
//下面代码创建两个Person对象
Animal an1 = new Cat(); //创建Cat对象,使用Animal类型的变量an1引用
Animal an2 = new Cat(); //创建Cat对象,使用Animal类型的变量an1引用
animalShout(an1); //调用animalShout()方法,将an1作为参数传递
animalShout(an2); //调用animalShout()方法,将an2作为参数传递
}
//定义静态的animalShout方法 ,接受一个Animal类型的参数
//参数,可以接受的是Animal接口的任何实现类对象
public static void animalShout(Animal an) {
Animal.shout(); //调用实际参数的shout()方法
}
}
1、将子类对象当中父类对象类型使用的情况,这在Java语言环境中称为“向上转型”
2、将子类对象当中父类对象使用时不需要任何显式的声明,需要注意的是,此时不能通过父类变量去调用子类中特有的方法
案例:
package Package3;
/*
* 多态中的转型
*/
//定义Animal接口
interface Animal{
public abstract void shout(); //定义抽象
}
//定义Cat类实现Animal接口
class Cat implements Animal{
//实现抽象方法shout()
public void shout() {
System.out.println("喵喵...");
}
//定义sleep()方法
public void sleep() {
System.out.print("猫睡觉...");
}
}
//定义测试类
public class Tas {
public static void main(String[] args) {
Cat cat = new Cat(); //创建Cat类的对象
}
//定义静态方法animalShout(),接收一个Animal类型的参数
public static void animalShout(Animal animal) {
animal.shout(); //调用传入参数animal的shout()方法
//animal.sleep(); //不能调用子类的特有方法
}
}
作用:可以对父类这个接口提升程序的扩展性
弊端:不能调用子类特有的方法,只能调用子父类的共有内容
在jdk中提供了一个Object类,它是类层次结构的根类,每个类都直接或间接继承自该类,所有对象包括数组都实现了这个类的方法常用方法
在Object类中定义了toString()方法,在该方法中输出了对象的基本信息,Object类中的toString()方法中的代码:
getClass().getName()+"@"+Integer.toHexString(ha shCode());
getClass().getName():代表返回对象所属类的类名
ha shCode():代表返回该对象的哈希值
Integer.toHexString(ha shCode()):代表将对象的哈希值用16进制表示
ha shCode()是Objest类中的一个方法
在编写程序时,在类里面定义的类称之为内部类,内部类是外部类的一个成员,Java内部类可以分为:成员内部类、方法内部类和匿名内部类等。
在前面多态的讲解中,如果方法的参数被定义为一个接口类型,那么就需要定义一个类来实现接口,并根据该类进行对象实例化,除此之外,还可以使用匿名内部类来实现接口,所谓匿名内部类就是没有名字的内部类,表面上看起来他似乎有名字,实际上那不是他的名字,当程序中使用匿名内部类时,在定义匿名内部类的地方往往直接创建该类的一个对象。
package cn.itcast.chapter04.task02;
public interface Careable {
public abstract void upKeep() ;
}
package cn.itcast.chapter04.task02;
public interface GPS {
public String showcoordinate();
}
package cn.itcast.chapter04.task02;
public class phone implements GPS {
public phone() {
super();
}
public String showcoordinate() {
String location="193,485";
return location;
}
}
package cn.itcast.chapter04.task02;
public class SendTask {
private String number;
private double goodsweight;
public SendTask() {
super();
}
public SendTask(String number, double goodsweight) {
super();
this.number = number;
this.goodsweight = goodsweight;
}
public void sendBefore() {
System.out.println("订单开始处理,仓库验货中...");
System.out.println("货物重量:"+this.getGoodsweight()+"公斤");
System.out.println("货物检验完毕");
System.out.println("货物填装完毕");
System.out.println("快递单号:"+this.getNumber());
}
public void send(Transportation t,GPS tool) {
System.out.println("运货人"+t.getAdmin()+
"正在驾驶编号为"+t.getNumber()+
"的"+t.getModel()+"发送货物!");
t.transport();
String showCoordinte=tool.showcoordinate();
String showCoordinate;
System.out.println("货物当前的坐标为:"+showCoordinte);
}
public void sendAfter(Transportation t) {
System.out.println("货物运输任务已完成");
System.out.println("运货人"+t.getAdmin()+"所驾驶的编号为"+t.getNumber()+"的"+t.getModel()+"已归还");
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public double getGoodsweight() {
return goodsweight;
}
public void setGoodsweight(double goodsweight) {
this.goodsweight = goodsweight;
}
}
package cn.itcast.chapter04.task02;
public class Task02Test {
public static void main(String[] args) {
SendTask task=new SendTask("HYX600235",76.34);
task.sendBefore();
System.out.println("===================");
ZTransportation t=new ZTransportation("2025","大奔","小韩");
phone p=new phone();
task.send(t, p);
System.out.println("====================");
task.sendAfter(t);
t.upKeep();
}
}
package cn.itcast.chapter04.task02;
public abstract class Transportation {
private String number;
private String model;
private String admin;
public Transportation() {
super();
}
public Transportation(String number, String model, String admin) {
super();
this.number = number;
this.model = model;
this.admin = admin;
}
public abstract void transport();
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getAdmin() {
return admin;
}
public void setAdmin(String admin) {
this.admin = admin;
}
}
package cn.itcast.chapter04.task02;
public class ZTransportation extends Transportation implements Careable{
public ZTransportation() {
super();
}
public ZTransportation(String number, String model, String admin) {
super(number, model, admin);
}
public void transport() {
System.out.println("运输进行中...");
}
public void upKeep() {
System.out.println("货物运输车辆保养完毕!");
}
}
运行结果: