面向对象
面向对象是一种符合人类思维习惯的编程思想,现实生活中存在各种形态不同形态不同的事物,这些事物之间存在着各种各样的联系。
面向对象的特点主要为封装性、继承性和多态性。
1、封装性
封装性是面向对象的核心思想,将对象的属性和行为封装起来,不需要让外界知道具体实现细节。
2、继承性
继承性主要描述的是类与 类之间的关系,通过继承,可以在无需重新编写原有类的情况下,对原有类的功能进行扩展。
3、多态
多态性指的是在程序中允许出现重名现象,它指在一个类中定义的属性和方法被其他类继承后,它们可以具有不同的数据类型或表现出不同的行为,使得同一个属性和方法在不同类中具有不同的语义。
类和对象
面向对象的编程思想,力图让程序中对事物的描述与该事物在现实中的形态保持一致。为了做到这一点,面对象的思想中提出了两个概念,即类和对象。类是对某一类事物的抽象描述,对象是用于表示现实中该类事物的个体。
类的定义
在面向对象的思想中最核心是对象,为了在程序中创建对象,首先需要定义一个类。类是对象的抽象,它用于描述一组对象的共同特性和行为。类中可以定义成员变量和成员方法,其中成员变量用于描述对象的特性,也被称作属性,成员方法用于描述对象的行为,可简称为方法。
代码示例:
/*
* 描述人事物
* 都是人的共性内容
*/
public class Person {
int age;//定义int类型变量age
//定义speak()方法
public void speak() {
System.out.println("大家好,我今年"+age+"岁");
}
}
类的设计
在Java中,对象是通过类创建出来的,因此,在程序设计时,最重要的就是类的设计。
假设要在程序中描述一个学校所有学生信息,可以先设置一个学生类(Student),在这个类中定义两个属性name、age分别表示学生的姓名和年龄,定一个方法introduce()表示学生做自我介绍。具体如下:
public class Student {
String name; //定义一个姓名属性int age; //定义一个年龄属性
public void introduce() {
//方法中打印属性name和age的值System.out.println("大家好,我叫" + name+ ",我今年" + age + "岁!");
}
}
对象的创建与使用
在Java程序中可以使用new关键字来创建对象,语法格式如下:
类名 对象名称=new 类名();
代码示例:
/*
* 创建对象,访问对象的成员
*/
public class PersonTest {
public static void main (String[] args) {
Person p1=new Person();//创建第一个Person类对象
Person p2=new Person();//创建第二个Person类对象
p1.age=18;//为age属性赋值
p1.speak();//调用对象的方法
}
}
运行结果:
类的封装
在设计一个类时,因该队成员变量的访问做出一些限定,不允许外界随意访问,这就需要现实类的封装。
所谓类的封装是指在定义一个类时,将类中的属性私有化,即使用private关键字来修饰,私有属性只能在它所在类中被访问,如果外界想要访问私有属性,需要提供一些使用public修饰的公有方法,其中包括用于获取属性值的getXxx方法和设置属性值的setXxx方法。
this关键字
this关键字用于表示本类当前的对象,当前对象不是某个new出来的实体对象,而是当前正在编辑的类。this关键字只能在本类中使用。
例如都声明age。但是这样做会又会导致成员变量和局部变量的名称冲突,在方法中将无法被访问成员变量age。为了解决这儿个问题,Java中提供了一个关键字this来指代当前对象,用于在方法中访问对象的其它成员。
超市购物程序案例
/*商品类
* 描述商品这个事物
*/
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<productArr.length;i++) {//循环遍历仓库中每一件商品
if(productArr[i].getproName()==name) {//如果找到名字和要买的商品名字一样
return productArr[i];//返回商品
}
}
return null;
}
}
/*
* 定义人类
* 描述人这个事物
* 人的名字
* 购物功能
*/
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()+"什么没买到");
}
}
}
运行结果 :
构造方法
构造方法的定义
一个类中定义的方法如果同时满足以下三个条件,该方法称为构造方法,具体如下:
- 方法名与类名相同
- 在方法名的前面没有返回值类型的声明
- 在方法中不能使用return语句返回一个值,但可以单独写return语句来作为方法的结束
构造方法的重载
与普通方法一样,构造方法也可以重载,在一个类中可以定义多个构造方法,只要每个构造方法的参数类型或参数个数不同即可。在创建对象时,可以通过调用不同的构造方法来为不同的属性进行赋值。
在Java中每个类都至少有一个构造方法,如果在一个类中没有定义构造方法,系统会自动为这个类创建一个默认的没有参数的构造方法。
垃圾回收
在Java中,当一个对象成为垃圾后仍会占用内存空间,时间一长,就会导致内存空间不足。针对这种情况,Java中引入了垃圾回收机制。
一个对象在称为垃圾后会暂时保存内存中,当这样的垃圾堆积到一定程度时,Java虚拟机会启动垃圾回收器将这些垃圾对象从内存中释放。
某些对象不是通过new操作符在内存中获取存储空间的,这种对象无法被垃圾回收机制识别。在Java中,提供了一个finalizer()方法
static关键字
静态变量
在定义一个类时,只是在描述某类事物的特征和行为,并没有产生具体的数据。只有通过new关键字创建该类的实例对象后,系统才会为每个对象分配空间,存储各自的数据。
在Java类中,可以使用static关键字来修饰成员变量,该变量被称为静态变量。静态变量被所有实例共享,可以使用“类名.变量名”的形式来访问。
静态方法
在一个静态方法中只能访问用static修饰的成员,原因在于没有被static修饰的成员需要先创建对象才能访问,而静态方法在被调用时可以不创建任何对象。
静态代码块
在Java类中,使用一对大括号包围起来的若干行代码被称为一个代码块,用static关键字修饰的代码块被称为静态代码块。当类被加载时,静态代码块会执行,由于类只加载一次,因此静态代码块只执行一次。在程序中,通常会使用静态代码块来对类的成员变量进行初始化。
成员内部类
在Java中,允许在一个类的内部类,这样的类称作内部类,这个内部类所在的类称作外部类。根据内部类的位置、修饰符和定义的方式可分为:成员内部类、静态内部类、方法内部类。
在一个类中除了可以定义成员变量、成员方法,还可以定义类, 这样的类称为成员内部类。在成员内部类中,可以访问外部类的所有成员。
如果想通过外部类去访问内部类,则需要通过外部类对象去创建内部类对象,创建内部类对象的语法格式:
外部类名.内部类名.变量名=new 外部类名().new 内部类名();
银行新用户现金业务办理代码案例
/*
* 定义银行类
* 属性:银行名称,储户名称,密码,余额,交易额度
* 功能:开门营业,存钱,取钱,关门
*/
public class Bank {
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();
}
}
运行结果:
类的继承
继承的概念
在程序中,继承描述的是事物之间所属关系,通过继承可以使多种事物之间形成一种关系体系。
在Java中,类的继承是指在一个现有类的基础上去构建一个新的类,构建出来的新类被称作子类,现有类被称作父类,子类会自动拥有父类所有可继承的属性和方法。在程序中,如果想声明一个类继承另一类,需要使用extends关键字。
在类的继承,需要注意一些问题,具体如下:
- 在Java中,类只支持单继承,不允许多继承,也就是说一个类只能有一个父类,但是多个类可以继承一个父类
- 在Java中,多层继承是可以的,即一个类的父类可以再去继承另外的父类
- 在Java中,子类在继承父类之后,创建子类对象的同时也会调用父类的构造方法
重写父类方法
在继承关系中,子类会自动继承父类中定义的方法,但有时在子类中需要对继承的方法进行一些修改,即对父类的方法进行重写。需要注意的是,在子类中重写的方法需要和父类被重写的方法具有相同的方法名、参数列表以及返回值类型。
super关键字
当子类重写父类的方法后,子类对象将无法访问父类被重写的方法,为了解决这个问题,在Java中专门提供了一个super关键字用于访问父类的成员。
1、使用super关键字访问父类的成员变量和成员方法。具体格式如下:
super.成员变量
super.成员方法([参数1,参数2...])
2、使用super关键字访问父类的构造方法,具体格式如下:
super([参数1,参数2...])
final关键字
Java中的类被final关键字修饰后,该类将不可以别继承,也就是不能够派生子类。
final关键字可用于修饰类、变量和方法,它有“无法改变”或者“最终”的含义,因此被final修饰的类、变量和方法将具体有以下特性:
- final修饰的类不能被继承
- final修饰的方法不能被子类重写
- final修饰的变量(成员变量和局部变量)是常量,只能复制一次
抽象类和接口
抽象类
当定义一个类时,常常需要定义一些方法来描述该类的行为特征,但有时这些方法的实现方式是无法确定的。
针对上面描述的情况,Java允许在定义方法时不写方法体,不包含方法体的方法为抽象方法,抽象方法必须使用abstract关键字来修饰,具体实例如下:
abstract void shout(); //定义抽象方法shout()
当一个类中包含了抽象方法,该类必须使用abstract关键字来修饰,使用abstract关键字修饰的类为抽象类。
在定义抽象类时需要注意,包含抽象方法的类必须声明为抽象类,但抽象类可以不包含任何抽象方法,只需要使用abstract关键字来修饰即可。另外,抽象类是不可以被实例化的,因为抽象类中可能包含抽象方法,抽象方法是没有方法体的,不可以被调用。如果想调用抽象类中定义的方法,则需要创建一个子类,在子类中将抽象类中的抽象方法进行实现。
接口
如果一个抽象类中的所有方法都是抽象的,则可以将这个类用另外一种方式来定义,即接口。接口是由常量和抽象方法组成的特殊类,是对象类的进一步抽象。
在定义接口时,需要使用interface关键字来声明,其语法格式如下:
public interface 接口名 extrends 接口1,接口2...
public static final 数据类型 常量名=常量值;
public abstract 返回值 抽象方法名(参数列表);
在上面的语法中,一个接口可以有多个父接口,他们之间用逗号隔开。Java使用接口的目的是为了克服单继承的限制,因为一个类只能有一个父类,而一个类可以实现多个接口。
由于接口中的方法都是抽象方法,因此不能通过实例化对象的方式来调用接口中的方法。此时需要定义一类,并使用implements关键字实现接口中所有的方法。一个类可以在继承的同时实现多个接口,在implements子句中用逗号隔开。接口的实现类声明格式如下:
修饰符 class 类名 extends 超类名 implements 接口1,接口2,...
USB接口程序设计代码案例
/*
* 定义一个名为USB的接口
*/
public interface USB {
public void turnOn();
public void turnOff();
}
/*
* 电脑类
* 有很多USB插槽
* 连接USB设备功能
* 开机功能,关机功能
*/
public class Computer {
//电脑上的USB插槽
private USB[] usbArr=new USB[4];
//向电脑上连接USB设备
public void add(USB usb) {
//遍历数组,获取所有的插槽
for(int i=0;i<usbArr.length;i++) {
if(usbArr[i]==null) {
//将设备连接在USB插槽上
//将USB接口实现类对象,存储到USB数组中
usbArr[i]=usb;
break;
}
}
}
//电脑的开机功能
public void powerOn() {
//循环遍历所有插槽
for(int i=0;i<usbArr.length;i++) {
//如果发现数组中存储了USB接口实现对象
if(usbArr[i]!=null) {
//调用设备上的开启功能
usbArr[i].turnOn();
}
}
System.out.println("电脑开机成功");
}
//电脑关机功能
public void powerOff() {
for(int i=0;i<usbArr.length;i++) {
if(usbArr[i]!=null) {
usbArr[i].turnOff();
}
}
System.out.println("电脑关机成功");
}
}
/*
* 键盘
*/
public class KeyBoard implements USB {
public void turnOn() {
System.out.println("键盘启动");
}
public void turnOff() {
System.out.println("键盘关闭");
}
}
/*
* 鼠标
*/
public class Mouse implements USB {
public void turnOn() {
System.out.println("鼠标启动");
}
public void turnOff(){
System.out.println("鼠标启动");
}
}
/*
* 麦克风
*/
public class Mic implements USB {
public void turnOn() {
System.out.println("麦克风启动");
}
public void turnOff() {
System.out.println("麦克风键盘启动");
}
}
/*
* 测试类
*/
public class Demo6{
public static void main(String[] args) {
//创建电脑对象
Computer c=new Computer();
//向电脑中添加USB设备,鼠标,麦克风和键盘设备
c.add(new Mouse());
c.add(new Mic());
c.add(new KeyBoard());
c.powerOn();//调用电脑的启动
System.out.println();
c.powerOff();//调用电脑的关机方法
}
}
运行结果:
多态
多态的概念
在同一个方法中,这种由于参数类型不同而导致执行效果各异的现象就是多态。继承是多态得以实现的基础。
在Java中为了实现多态,允许使用一个父类类型的变量来引用一个子类类型的对象,根据被引用子类对象特征的不同,得到不同的运行结果。
多态的类型转换
将子类对象当作父类类型的情况,Java的语言环境中称为“向上转型”。
将子类对象当作父类使用时不需要任何显式声明,需要注意是的,此时不能通过父类变量去调用子类中的特有方法。
向上转型子类提升父类,实现类提升为了接口类型。如果调用实现类或者是子类中的特有方法,类型的向下转型,数据类型的向下转型,需要强制转换
多态的好处对父类或者接口提供程序的扩展性,坏处能调用子父类的共有属性,不能调有子类的特有属性。
Object类
Object类是层次结构的根类,每个类都直接或间接继承自该类,所有对象(包括数组P)都实现了这个类的方法
方法名称 | 方法说明 |
equals() | 指定其他某个对象是否与此对象“相等” |
getClass() | 返回此 Object的运行时类 |
hashCode() | 返回该对象的哈希码值 |
toString() | 返回该对象的字符串表示 |
匿名内部类
在编写Java程序时,在类里面定义的类称之为内部类,内部类时外部类的一个成员。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("货物运输车辆保养完毕!");
}
}
运行结果:
目录