一、面向对象的概念
面向对象思想是人类最自然的一种思考方式,它将所有预处理的问题抽象为对象,通过了解这些对象具有哪些相应的属性以及展示这些对象的行为,以解决这些对象面临的一些实际问题。在从程序开发中引入面向对象设计的概念,其实质就是现实世界中的对象进行建模操作。
面向对象的特点
主要可以概括为封装性、继承性和多态性。
1.封装性
封装是面向对象编程的核心思想,将对象的属性和行为封装起来,其载体就是类,类通常对客户隐藏其实现细节,这就是封装思想。采用封装思想保证了类的内部数据结构的完整性,使用类的用户不能轻易地操作类的数据结构,只能执行类允许公开的数据,这样子避免了外部操作和内部数据影响,提高了程序的可维护性。
2.继承性
(1)继承是Java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。
(2)继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。例如:
3.多态性
(1)多态是同一个行为具有多个不同表现形式或形态的能力。
(2)多态就是同一个接口,使用不同的实例而执行不同操作。
二、类的定义
1.对象
在面向对象的思想中,最核心的就是对象,为了在程序中创建对象,首先需要定义一个类,类是对象的抽象,它用于描述一组对象的共同特征和行为。类中可以定义成员变量和成员方法,其中成员变量用于描述对象的特征,也被称作属性,成员方法用于描述对象的行为,可简称为方法。
public class expl1 {
// 描述人事物
// 都是人的共性内容
int age = 10;// 定义int类型变量age1定义speak()方法
public void speak () {
int age=60;
System.out.println("大家好,我今年"+ age +"岁");
}
}
2.对象的创建与使用
应用程序想完成具体的功能,仅有类是远远不够的,还需要根据类创建实例对象。在java程序中可以使用new关键字来创建对象,具体格式如下:
类名 对象名称 = new 类名();
例如,创建person类的实例对象代码如下:
Person p = new Person();
上面代码中,“new Person()”用于创建Person类的一个实例对象,“Person p”则是声明了一个Person类型的p变量。中间的等号用于将Person对象在内存中的地址赋值给变量p,这样变量p便有了对象的引用。在内存中变量p和对象之间的引用关系。
三、类的设计
在Java中,对象是通过类创建出来的。因此,在程序设计时,最重要的就是类的设计。接下来就通过一个具体的案例来学习如何设计一个类。
假设要在程序中描述一个学校所有学生的信息,可以先设计一个学生类(student),在这个类中定义两个属性name、age分别表示学生的姓名和年龄定义一个方法introduce()表示学生做自我介绍。根据上面的描述设计出来的Student类如下所示。
//用于描述学生信息的类
//属性:name,age成员变量形式定义
//行为:自我介绍方法introduce()
public class Student {
String name;//定义一个姓名属性
int age; //定义一个年龄属性
public void introduce(){
//方法中打印属性name和age的值
System.out.println("大家好,我叫"+name+"我今年"+age+"岁!");
四、类的封装
1.在设计一个类时,应该对成员变量的访问作出一些限定,不允许外界随意访问,这就鸳要实现类的封装。
2.所谓类的封装是指在定义一个类时,将类中的属性私有化,即使用private关键字来修饰,私有属性只能在它所在类中被访问,如果外界想要访问私有属性,需要提供一些使用public修饰的公有方法,其中包括用于获取属性值的get()方法和设置属性值的set()方法。
//实现类的封装
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()
reutrn age;
}
public void setAge(int stuAge){
age = stuAge;
}
public void introduce(){
System.out.println("大家好,我叫"+name+",我今年"+age+"岁");
}
}
public class Example04{
public static void main(String[] args){
Studnet stu = new Studnet();
stu.setAge(30);
stu.setName("韩强");
stu.introduce();
}
}
权限修饰符
(1)在Java中的权限修饰符主要包括private、public和protected,这些修饰符控制着对类和类的成员变量以及成员方法的访问,如果一个类的成员变量或成员方法被修饰为private,则该成员变量只能在本类中使用,在子类中是不可见的,并且对其他包的类也是不可见的。
(2)如果将类的成员变量和成员方法的访问权限设置为public,那么除了可以在本类使用这些数据,以免用户直接访问它。如果需要使类中的数据被子类或其他包中的类使用,可以将这个类设置为public访问权限。
(3)如果一个类使用protected修饰符,那么只有本包内的该类的子类或其他可以访问此类中的成员变量和成员方法。
(4)public和protected修饰符的类可以由子类访问,如果子类和父类不在同一个包中,那么只有修饰符为public的类可以被子类进行访问。如果父类不允许通过继承产生的子类访问它的成员变量,那么必须使用private声明父类的这个成员变量。如下表描述了private,protected,public,default修饰符的修饰权限。
【案例代码】超市购物程序设计
//商品类
//描述商品这个事物
public class Produet {
private String proName ; //商品名
public String getProName () {return proName;}
public void setProNane (String proName) {
this.proName = proName;}
}
//定义个超市类
//描述超市事物
//超市名字
//超市的仓库,存储商品
//售货方法
public class Market{
private String marketName;//超市名字
private Produet[] produetArr;//仓库,存储商品,里面存储若干商品
public String getmarketName(){
return marketName;
}
public void setMarketName(String marketName){
this.marketName=marketName;
}
public Produet[] getProduetArr() {
return produetArr ;
}
public void setProduetArr(Produet[]produetArr) {
this.produetArr=produetArr;
}
public Produet sell(String name) {//卖货
for(int i=0;i<produetArr.length;i++) {//遍历循环仓库中每一个商品
if(produetArr[i].getProName()==name) {
return produetArr[i];
}
}
return null;
}
}
package 第二篇复习;
//定义人类
//描述人这个事物
//人的名字
//购物功能
public class people {
private String name;//人名
public String getName() {return name;}
public void setName(String name) {
this.name=name;
}
public Produet shopping(Market market,String name) {//购物,指定去哪个超市,商品名
return market.sell(name); //调用超市的卖货方法,指定商品名字,把卖出的货结果返回
}
}
public class shopping {
public static void main(String[] args) {
//创建商品对象,给商品名字赋值
Produet p1=new Produet();
Produet p2=new Produet();
Produet p3=new Produet();
Produet p4 =new Produet();
Produet p5=new Produet();
p1.setProNane("电视机");
p2.setProNane("豆浆机");
p3.setProNane("洗衣机");
p4.setProNane("空调机");
p5.setProNane("吹风机");
//创建超市对象,给超市名字赋值,给仓库赋值
Market m=new Market();
m.setMarketName("家乐福");
m.setProduetArr(new Produet[]{p1,p2,p3,p4,p5});
//创建购物者,给名字赋值
people p=new people();
p.setName("小强");
//调用购物者的购物方法,指定超市和商品,得到结果
Produet result=p.shopping(m, "豆浆机");
if(result!=null) {
System.out.println(p.getName()+"在"+m.getmarketName()+"买到了"+result.getProName());
}else {
System.out.println(p.getName()+"白跑一趟, 在"+m.getmarketName()+"什么也没买到");
}
}
}
五、构造方法
1.构造方法的定义
满足三个条件:
1.方法名与类名相同
2.在方法名的前面没有返回值类型的声明
3.在方法不能使用return语句返回一个值,但是可以单独写return语句来作为方法的结束
例题如下
2.构造方法的重载
1.在一个类可以定义多个构造方法,只要每个构造方法的参数类型或参数个数不同即可。
2.在创建对象时,可以通过调用不同的构造方法来为不同的属性进行赋值。
六、 this关键字
(1)this关键字用于表示当前对象不是某个new出来的实体对象,而是当前正在编译的类,this关键字只能在本类中使用。
(2)用法:
七、垃圾回收
在Java中对象成为垃圾后仍会占用内存空间,时间一长,就会导致内存空间的不足。针对这种情况,Java中引入了垃圾回收机制。有了这种机制,程序员不需要过多关心垃圾对象回收的问题,Java虚拟机会自动回收垃圾对象所占用的内存空间。
一个对象在成为垃圾后会暂时地保留在内存中,当这样的垃圾堆积到一定程度时Java虚拟机就会启动垃圾回收器将这些垃圾对象从内存中释放,从而使程序获得更多可用的内存空间。除了等待Java虚拟机进行自动垃圾回收外,还可以通过调用Svstem.g()方法来通知Java虚拟机立即进行垃圾回收。当一个对象在内存中被释放时,它的finalize()方法会被自动调用,因此可以在类中通过定义finalize()方法来观察对象何时被释放。
八、static关键字
静态变量
(1)static关键字修饰的变量和方法被称为静态变量和静态方法。
(2)被声明为static的变量和方法被称为静态成员。静态成员属于类所有,区别于个别对象,可以在本类或其他类使用类名和“,”运算符调用静态成员。语法如下:
类名.静态类成员
静态方法
要实现这样的效果,只需要在类中定义的方法前加上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; // 交易额
// 静态方法,打印欢迎语句
static void welcome() {
System.out.println("欢迎来到" + bankName + "------------");
}
// 开户,构造方法
// 可以右键自动生成
public Bank(String name, String password,double turnover) {
this.name = name;
this.password = password;
this.turnover = turnover;
this.balance = 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 (this.balance < turnover) {
System.out.println("您的余额不足");
} else {
balance = balance - turnover;
System.out.println(name + "您好,您的帐户已取出" + turnover + "元,您的帐户余额是"
+ balance + "元");
}
}
// 静态方法,打印欢迎下次光临
static void welcomeNext() {
System.out.println("欢饮下次光临" + bankName + "------------");
}
}
public class Trade {
public static void main(String[] args) {
// 定义一家银行(给静态变量赋值,可以直接使用类名访问)
Bank.bankName = "招商银行";
// 调用静态方法,打印欢迎语句
Bank.welcome();
// 通过构造方法进行开户操作
Bank bank = new Bank("小梦", "654321", 10);
// 进行存款操作
bank.deposit(500);
// 取款时密码错误
bank.withdrawal("234567", 50);
// 取款时余额不足
bank.withdrawal("123456", 200);
// 成功取款
bank.withdrawal("654321", 1000);
// 调用静态方法,打印离开语句
Bank.welcomeNext();
}
}
九、类的继承
继承的概念
1.继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。
2.继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类3.从父类继承方法,使得子类具有父类相同的行为。
4.生活中的继承
兔子和羊属于食草动物类,狮子和豹属于食肉动物类。
食草动物和食肉动物又是属于动物类。
所以继承需要符合的关系是:is-a,父类更通用,子类更具体。
虽然食草动物和食肉动物都是属于动物,但是两者的属性和行为上有差别,所以子类会具有父类的一般特性也会具有自身的特性。
5. 在Java中,类的继承是指在一个现有类的基础上去构建一个新的类构建出来的新类被称作子类,现有类被称作父类,子类会自动拥有父类所有可继承的属性和方法。在程序中,如果想声明一个类继承另一个类,需要使用extends关键字。
格式与例题:
父类
public class 父类类名{
}
子类需要继承父类
public class 子类类名 extends 父类类名{
}
//类的继承
//定义A类,作为父类
class A{
String name;//定义name属性
//定义动物叫的方法
public void shout(){
System.out.println("动物发出叫声");
}
}
//定义Dog类继承A类,关键字extends
class Dog extends A{
//定义一个打印name属性的方法
System.out.println("name"+name);
}
}
//定义测试类
public class Example{
public static void main(String[] args){
Dog dog = new Dog();//创建一个Dog类的对象,子类的对象
dog.name = "边牧犬";//为Dog类的name属性进行赋值
dog.printName();//调用Dog类的输出名字的方法
dog.shout();//调用Dog类继承的父类的方法
}
}
在类的继承中,需要注意一些问题,具体如下:
在Java中,类只支持单继承,不允许多重继承,也就是说一个类只能有一个父类,例如下面这种情况是不合法的。
class A{};
class B{};
class C extends A,B{}//C类不可以同时继承A类和B类。
多个类可以继承一个父类,例如下面这种情况是允许的。
class A{}
class B extends A{}
class C extends A{}//A类和B类都可以继承A类
在Java中,多层继承是可以的,即一个类的父类可以再去继承它的父类,例如我可以继承我父亲的,我父亲可以继承我爷爷的。例如下面这种情况是允许的
class A{}
class B extends A{}//B类继承A类,B类是A类的子类
class C extends B{}//C类继承B类,C类是B类的子类,也是A类的子类
重写父类方法
当一个子类继承一个父类的时候,可以重写覆盖原来父类里面的方法,这个方法要求和父类方法的名称相同,参数列表相同。
重写:需要有继承关系,子类重写父类的方法
super关键字
super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
当子类重写父类的方法后,子类对象将无法访问父类被重写的方法,为了解决这个问题,在Java中专门提供了一个super关键字用于访问父类的成员。例如访问父类的成员变量、成员方法和构造方法。接下来分两种情况来学习一下super关键字的具体用法。
1.使用super关键字访问父类的成员变量和成员方法。具体格式如下
super.成员变量
super.成员方法([参数1,参数2...])
2.使用super关键字访问父类的构造方法。具体格式如下:
super([参数1,参数2..])
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 调用父类方法
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Animal();
a.eat();
Dog d = new Dog();
d.eatTest();
}
}
final关键字
final 可以用来修饰变量(包括类属性、对象属性、局部变量和形参)、方法(包括类方法和对象方法)和类。
final 含义为 "最终的"。
使用 final 关键字声明类,就是把类定义定义为最终类,不能被继承,或者用于修饰方法,该方法不能被子类重写:
-
声明类:
final class 类名 {//类体}
-
声明方法:
修饰符(public/private/default/protected) final 返回值类型 方法名(){//方法体}
注: final 定义的类,其中的属性、方法不是 final 的。
例题:
十、抽象类和接口
抽象类
当定义一个类时,常常需要定义一些方法来描述该类的行为特征,但有时这些方法的实现方式是无法确定的。例如前面在定义Animal类时,shout()方法用于表示动物的叫声,但是针对不同的动物,叫声也是不同的,因此在shout()方法中无法准确描述动物的叫声。
针对上面描述的情况,Java允许在定义方法时不写方法体,不包含方法体的方法为抽象方法,抽象方法必须使用abstract关键宇来修饰,具体示例如下:
abstract void shout(: // 定义抽象方法 shout()
//抽象类的使用
//定义抽象类Animal
abstract class Animal{
public abstract void shout(); //定义抽象方法
public void sleep() {
System.out.println("动物在睡觉");
}
}
//Animal需要子类继承来使用
//定义Dog类继承Animal抽象类
class Dog extends Animal{
//重写父类的抽象方法,实习抽象方法
public void shout() {
System.out.println("汪汪....");
}
}
//定义测试类
public class example10 {
public static void main(String[] args) {
Dog dog=new Dog();//创建Dog类的对象,创建的是抽象类的子类对象
dog.shout();
dog.sleep();
}
}
抽象类总结
1. 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。
2. 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
3. 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。
4. 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。
5. 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。
接口
接口的实现
使用接口可以实现多重继承,一个类可以同时实现多个接口,于是可以将所有需要继承的接口放置implements关键字后使用逗号隔开。
当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类。
类使用implements关键字实现接口。在类声明中,Implements关键字放在class声明后面。
实现一个接口的语法,可以使用这个公式:
接口语法:
修饰符 class 类名 implement 接口1,接口2....{
}
十一、多态
(1)多态的概念
在设计一个方法时,通常希望该方法具备一定的通用性。例如要实现一个动物叫的方法,由于每种动物的叫声是不同的,因此可以在方法中接收一个动物类型的参数,当传入猫类对象时就发出猫类的叫声,传入犬类对象时就发出犬类的叫声。
在同一个方法中,这种由于参数类型不同而导致执行效果各异的现象就是多态。继承是多态得以实现的基础。
在Java中为了实现多态,允许使用一个父类类型的变量来引用一个子类类型的对象,根据被引用子类对象特征的不同,得到不同的运行结果。
利用多态可以使程序具有良好的扩展性,并可以对所有类对象进行通用的处理。
假如现在要编写一个绘制图形的方法draw(),如果传入正方形对象将绘制正方形,如果传入圆形对象就绘制圆形,这种场景可以使用重载来实现,定义如下:
public void draw(Square s){
//绘制正方形的方法
}
public void draw(Circular c){
//绘制圆形方法
}
(2)多态的类型转换
对象类型的转换在java编程中经常遇到,主要包括向上转型和向下转型操作
1.向上转型
向上转型:将子类对象赋值给父类引用
(自动类型转换)
格式:Animal a=new Dog();
2.向下转型
向下转型:将父类对象赋值给子类引用
(需要进行强制类型转换)
格式:Dog a=(Dog) new Animal();
3.Object类
在Object类中,主要包括clone(),finalize(),equals(),toString()等方法,其中常用的两个方法为equals()和toString()方法。由于所有的类都是object类的子类,所以任何类都可以重写object类中的方法。
getClass()方法
getClass()方法是object类定义的方法,它会返回对象执行的Class实例,然后使用该实例调用getName()方法可以取得类的名称。语法如下:
getClass().getname();
方法的重写
返回参数相同,方法名相同,传入参数相同,方法体不同
to String ()方法
tostring()的功能是将一个对象返回为字符串形式,它会返回一个String实例,在实际的应用中通常重写tostring()方法,为对象提供一个特定的输出的模式,当这个类转换为字符串或与字符串连接时,将自动调用用重写的tostring()方法。
equals()方法
在Java语言中,有两种比较对象的方式,分别为“==”运算符与equals()方法,两者区别在于:“==”比较的是两个对象引用内存地址是否相等,而equals()方法比较的是两个对象的实际内容,所以equals()方法判断出了这两个对象实际上是同一个,而“==”运算符无法做出有效判断,如果两个对象类型的不同,那么equals()方法就会认为两者都不同 。