5.1 面向对象的概念
一个对象有不同的属性,这些属性对应不同的方法
面向对象的三大特性:封装、继承、多态
封装性:一是指把对象的属性和行为看成是一个密不可分的整体,将这两者“封装”在一起(即封装在对象中);另外一层含义指“信息隐藏”,将不想让外界知道的信息隐藏起来。例如,驾校的学员学开车,只需要知道如何操作汽车,无需知道汽车内部是如何工作的。
继承性:描述类和类之间的关系,继承性主要描述的是类与类之间的关系,通过继承,可以在无需重新编写原有类的情况下,对原有类的功能进行扩展。
多态性:多态性指的是在一个类中定义的属性和方法被其它类继承后,它们可以具有不同的数据类型或表现出不同的行为,这使得同一个属性和方法在不同的类中具有不同的语义。不同的子类对同一种方法有不同的反应
示例代码:
package llll;
public class Student {
String id;
String name;
int age;
String address;
public Student(String id,String name,int age,String address) {
this.id = id;
this.name = name;
this.age = age;
this.address = address;}
public String getid() {
return(this.id);}
public void setid(String id) {
this.id = id;}
public String getname() {
return(this.name);}
public void setname(String name) {
this.name = name;}
public int getage() {
return(this.age);}
public void setage(int age) {
this.age = age;}
public String getaddress() {
return(this.address);}
public void setaddress(String address) {
this.address = address;}
}
5.2 类与对象
类表示某类群体的一些基本特征抽象,对象表示一个个具体的事物。
5.2.1 类的定义
(1)代码格式
class Student {
String name; // 定义String类型的变量name
int age; // 定义int类型的变量age
String sex; // 定义String类型的变量sex
// 定义 read () 方法
void read() { System.out.println("大家好,我是" + name + ",我在看书!"); } }
5.2.2 局部变量和成员变量
在方法中的变量时局部变量,在类下的变量是成员变量
5.2.3 对象的创建和使用
(1)创建
类名 对象名称 = new 类名();
例如:
Student stu = new Student();
(2)使用
有两个,第一个给属性赋值:stu.name = '王俊凯';调用对象的方法:stu.read(),,就可以调用这个方法
5.2.4 访问控制
针对类、成员方法和属性,Java提供了4种访问控制权限
访问权限从小到大如下图所示:
(1)private 在本类中才可以访问
(2)default 在同一个包中可以访问
(3)protected 只能被本包及不同包的子类访问
(4)public 都可以
5.2.5 文件命名的要求
注意:如果一个Java源文件中定义的所有类都没有使用public修饰,那么这个Java源文件的文件名可以是一切合法的文件名;如果一个源文件中定义了一个public修饰的类,那么这个源文件的文件名必须与public修饰的类名相同。!!!!
5.3 实现封装
在类的外部不能实现对属性的赋值,对属性的赋值通过方法实现,这样就实现了封装性
(1)实现代码
有参的构造方法:
注意申明变量时前面不能写public了
class Student{
private String name;
private int age;
public Student(String n, int a) {
this.name = n;
this.age = a;
}}
实例化对象时直接写成:
Student stu = new Student("张三",18);
如果要修改属性,使用stu.name = "李四",会失败。则如果父类中的属性都是private是,要定义修改方法:setname(),这样就可以在外部进行修改了。
注意:
在Java中的每个类都至少有一个构造方法,如果在一个类中没有定义构造方法,系统会自动为这个类创建一个默认的构造方法,这个默认的构造方法没有参数,方法体中没有任何代码,即什么也不做。
5.4 this关键字(构造方法中使用)
使用this关键字 区分成员变量与局部变量,为了避免出现下图的情况
只用在构造方法时用上!表示当前的变量的名字,即写成这种形式
5.5 static关键字(共享属性)
如果希望某些属性被所有对象共享,就必须将其声明为static属性。如果属性使用了static关键字进行修饰,则该属性可以直接使用类名称进行调用。
两个关键点:1、被static修饰的属性共享 2、被static修饰的方法的调用用类名 3、用static修饰代码块则只会运行一次
代码格式:
案例1:【对属性】A大学改名为B大学,将10万个学生的属性进行更改
package four;
import java.util.Scanner;
public class Demo {
public static void main(String[] args) {
Student stu1 = new Student("张三",18);
Student stu2 = new Student("王五",19);
Student stu3 = new Student("李二",20);
System.out.println(stu1.info());
System.out.println(stu2.info());
System.out.println(stu3.info());
// System.out.println(stu.name);
stu1.school = "B大学";
System.out.println(stu1.info());
System.out.println(stu2.info());
System.out.println(stu3.info());
}
}
结果:
改了一个但是大家的大学都变了。
实例2:【对方法】
public static String getSchool() {
return school;
public static void setSchool(String school) {
Student.school = school;
Student.setSchool("B大学");//这句实现全部更改
实例3:静态代码块【只被调用了一次】
package four;
public class Student {
String name; //成员属性
{
System.out.println("我是构造代码块");
}
static {
System.out.println("我是静态代码块");
}
public Student(){ //构造方法
System.out.println("我是Student类的构造方法");
}}
结果:
5.6 继承的概念
子类继承父类的属性和方法,使得子类对象(实例)具有父类的特征和行为
class 父类{
……
}
class 子类 extends 父类{
……
}
直接继承:
//第一个
public class Animal {
private String name; // 定义name属性
private int age; // 定义name属性
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//第二个
public class Dog extends Animal {
//此处不写任何代码
}
//第三个
public class Example01 {
public static void main(String[] args) {
Dog dog = new Dog(); // 创建一个Dog类的实例对象
dog.setName("牧羊犬"); // 此时访问的方法时父类中的,子类中并没有定义
dog.setAge(3); // 此时访问的方法时父类中的,子类中并没有定义
System.out.println("名称:"+dog.getName()+",年龄:"+dog.getAge());
}
}
运行结果:
继承时加上自己的方法:
// 定义Dog类继承Animal类
class Dog extends Animal {
private String color; // 定义name属性
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
public class Example01 {
public static void main(String[] args) {
Dog dog = new Dog(); // 创建一个Dog类的实例对象
dog.setName("牧羊犬"); // 此时访问的方法时父类中的,子类中并没有定义
dog.setAge(3); // 此时访问的方法时父类中的,子类中并没有定义
dog.setColor("white");
System.out.println("名称:"+dog.getName()+",年龄:"+dog.getAge()+",颜色:"+dog.getColor());
}
}
继承时需要注意的问题:
(1)在Java中,类只支持单继承,不允许多重继承。也就是说一个类只能有一个直接父类,例如下面这种情况是不合法的。
class A{} class B{}
class C extends A,B{} // C类不可以同时继承A类和B类
(2)多个类可以继承一个父类,例如下面这种情况是允许的。
class A{}
class B extends A{}
class C extends A{} // 类B和类C都可以继承类A
(3)在Java中,多层继承也是可以的,即一个类的父类可以再继承另外的父类。例如,C类继承自B类,而B类又可以继承自A类,这时,C类也可称作A类的子类。例如下面这种情况是允许的。
class A{}
class B extends A{} // 类B继承类A,类B是类A的子类
class C extends B{} // 类C继承类B,类C是类B的子类,同时也是类A的子类
5.7 方法的重写
直接覆盖掉注意权限的设定,新方法的权限不能比老方法的权限低
// 定义Animal类
class Animal {
//定义动物叫的方法
void shout() {
System.out.println("动物发出叫声");
}
}
// 定义Dog类继承动物类
class Dog extends Animal {
//重写父类Animal中的shout()方法
void shout() {
System.out.println("汪汪汪……");
}
}
// 定义测试类
public class Example03 {
public static void main(String[] args) {
Dog dog = new Dog(); // 创建Dog类的实例对象
dog.shout(); // 调用dog重写的shout()方法
}
}
java代码只有有main才可以运行
5.8 super关键字(调用父类中被覆盖的方法)
用于调用父类中被覆盖的方法!
当子类重写父类的方法后,子类对象将无法访问父类被重写的方法,为了解决这个问题,Java提供了super关键字,super关键字可以在子类中调用父类的普通属性、方法以及构造方法。
具体用法:
接下来详细讲解super关键字的具体用法。 (1)使用super关键字访问父类的成员变量和成员方法,具体格式如下:
super.成员变量
super.成员方法(参数1,参数2…)
案例1:扩充父类中的方法【直接使用父类方法运行的结果】
public String info() {
return super.info()+",颜色:"+this.getColor();} //扩充父类中的方法
注意:通过super()调用父类构造方法的代码必须位于子类构造方法的第一行,并且只能出现一次
5.9 final 关键字(不可继承)
Java中的类被final关键字修饰后,该类将不可以被继承,即不能够派生子类。
final class Animal {}
当一个类的方法被final关键字修饰后,这个类的子类将不能重写该方法。
Java中被final修饰的变量是为常量,常量只能在声明时被赋值一次,在后面的程序中,其值不能被改变。
final int AGE = 18;
5.10 抽象类
类的行为特征不一致
5.10.1 抽象类定义
代码格式:
abstract class 抽象类名称{
访问权限 返回值类型 方法名称(参数){
return [返回值]; }
访问权限 abstract 返回值类型 抽象方法名称(参数); //抽象方法,无方法体 }
抽象类的定义规则如下:
(1)包含一个以上抽象方法的类必须是抽象类。
(2)抽象类和抽象方法都要使用abstract关键字声明。
(3)抽象方法只需声明而不需要实现。
(4)如果一个类继承了抽象类,那么该子类必须实现抽象类中的全部抽象方法。
注意:使用abstract关键字修饰的抽象方法不能使用private修饰,因为抽象方法必须被子类实现,如果使用了private声明,则子类无法实现该方法。
5.10.2 抽象方法定义
定义格式:abstract void 方法名称(参数);
1 // 定义抽象类Animal
2 abstract class Animal {
3 // 定义抽象方法shout()
4 abstract void shout();
5 }
6 // 定义Dog类继承抽象类Animal
7 class Dog extends Animal {
8 // 实现抽象方法shout()
9 void shout() {
10 System.out.println("汪汪...");
11 }
12 }
13 // 定义测试类
14 public class Example10 {
15 public static void main(String[] args) {
16 Dog dog = new Dog(); // 创建Dog类的实例对象
17 dog.shout(); // 调用dog对象的shout()方法
18 }
19 }
5.11 接口
如果一个抽象类的所有方法都是抽象的,则可以将这个类定义接口。接口是Java中最重要的概念之一,接口是一种特殊的类,由全局常量和公共的抽象方法组成,不能包含普通方法。
代码格式:
(1)接口定义和继承 代码格式:
方法没有返回对象就写 void!
public interface 接口名 extends 接口1,接口2... {
public static final 数据类型 常量名 = 常量值;
public default 返回值类型 抽象方法名(参数列表);
public abstract 返回值类型 方法名(参数列表);//没有方法体时这样写
public abstract 返回值类型 方法名(参数列表){ //默认方法的方法体 }
public abstract 返回值类型方法名(参数列表){ //类方法的方法体 } }
注意:1、JDK 8对接口进行了重新定义,接口中除了抽象方法外,还可以有默认方法和静态方法(也叫类方法),默认方法使用default修饰,静态方法使用static修饰,且这两种方法都允许有方法体。
2、“extends 接口1,接口2...”表示一个接口可以有多个父接口,父接口之间使用逗号分隔。Java使用接口的目的是为了克服单继承的限制,因为一个类只能有一个父类,而一个接口可以同时继承多个父接口。
3、接口中的变量默认使用“public static final”进行修饰,即全局常量。接口中定义的方法默认使用“public abstract”进行修饰,即抽象方法。如果接口声明为public,则接口中的变量和方法全部为public。
4、不管写不写访问权限,接口中的方法访问权限永远是public。与此类似,在接口中定义常量时,可以省略前面的“public static final”,此时,接口会默认为常量添加“public static final”。
(2)定义类实现接口的功能 代码格式:
修饰符 class 类名 implements 接口1,接口2,...{
... }
注:类中的方法要将接口中的所有方法都写一遍
案例:
案例1:打印不同边长的正方形
//创建接口
package four;
public interface MyPrint {
public abstract void show();
}
//创建类实现接口
package four;
import java.util.Scanner;
//创建类
public class MyPrintSquare implements MyPrint {
@Override
public void show() {
//重新改写void方法
//创建scanner
Scanner in = new Scanner(System.in);
System.out.println("请输入一个数字");
int a = in.nextInt(); //获取是多大的正方形后开始打印
int i;
int j;
for (i=0;i<a;i++) {
for (j=0;j<a;j++) {
System.out.print("* ");
}
System.out.println();
}
}
}
//定义测试类
package four;
import java.util.Scanner;
public class MyPrintTest {
public static void main(String[] args) {
MyPrintSquare n =new MyPrintSquare();
n.show();
//
}
}
运行结果:
5.12 多态概述
在Java中,多态是指不同对象在调用同一个方法时表现出的多种不同行为。
Java中多态主要有以下两种形式: (1)方法的重载。 (2)对象的多态性(方法重写)。
5.13 对象类型的转换
介绍:
父类转换成子类,或者子类转换成父类。比如Animal转换成Dog这种情况。
对象类型转换主要分为以下两种情况: (1)向上转型:子类对象→父类对象。 (2)向下转型:父类对象→子类对象。 对于向上转型,程序会自动完成,而向下转型时,必须指明要转型的子类类型。
代码格式:
对象向上转型:父类类型 父类对象 = 子类实例;
对象向下转型: 父类类型 父类对象 = 子类实例;
子类类型 子类对象 = (子类)父类对象;
向上转型:
Dog dog = new Dog(); // 创建Dog对象
Animal an = dog; //变成Animal了
an.shout();
但是结果是:汪汪,还是狗叫,说明虽然是父类对象但是还是调用的子类的方法。
但是父类不能调用父类未定义的方法。
向下转型:
向下转型之前必须有向上转型!
Animal an = new Dog(); // 此时发生了向上转型,子类→父类
Dog dog = (Dog)an; // 此时发生了向下转型
dog.shout();
dog.eat();
结果:
5.14 instanceof关键字(判断对象是否某个类(或接口))
instanceof关键字判断一个对象是否是某个类(或接口)的实例
代码格式:
对象 instanceof类(或接口)
如果对象是指定的类的实例对象,则返回true,否则返回false。
a1 instanceof Animal
案例1:经理与员工工资案例
假设每次给员工涨工资一次能涨10,经理能涨20%。本案例要求利用多态实现给员工和经理涨工资。
package com.itheima;
abstract class Person{
protected String name;
protected String address;
void setName(String name){
this.name = name;
}
void setAddress(String address){
this.address = address;
}
String getName(){
return name;
}
String getAddress(){
return address;
}
void add(int salary){
}
}
class Employee extends Person{
protected String number;
protected double salary;
protected int age;
public Employee(){}
public Employee(String name, String address, String number, double salary, int age){
this.name = name;
this.address = address;
this.number = number;
this.salary = salary;
this.age = age;
}
void setNumber(String number)
{
this.number = number;
}
void setSalary(double salary)
{
this.salary = salary;
}
void setAge(int age)
{
this.age = age;
}
String getNumber(){
return number;
}
double getSalary(){
return salary;
}
int getAge(){
return age;
}
void add()
{
this.salary *= 1.1;
}
}
class Manager extends Employee{
private String rank;
public Manager(String name, String address, String number, double salary, int age, String rank){
this.name = name;
this.address = address;
this.number = number;
this.salary = salary;
this.age = age;
this.rank = rank;
}
void add() {
this.salary *= 1.2;
}
void setRank(String rank){
this.rank = rank;
}
String getRank(){
return rank;
}
}
public class Main{
public static void main(String[] args){
Employee worker = new Employee("张三","广东清远","9527",3000.0, 2);
Manager manager1 = new Manager("李四","广东清远", "1122",10000.0,5,"高级经理");
Manager manager2 = new Manager("王五","广东清远", "1100",8000.0,4,"经理");
System.out.println("原有工资:");
System.out.println("员工的工资:"+worker.getSalary());
System.out.println("高级经理的工资:"+manager1.getSalary());
System.out.println("经理的工资:"+manager2.getSalary());
worker.add();
manager1.add();
manager2.add();
System.out.println("涨工资后:");
System.out.println("员工的工资:"+worker.getSalary());
System.out.println("高级经理的工资:"+manager1.getSalary());
System.out.println("经理的工资:"+manager2.getSalary());
}
}
5.15 Object关键字(所有类的父类)
每个类都直接或间接继承Object类,因此Object类通常被称之为超类。当定义一个类时,如果没有使用extends关键字为这个类显式地指定父类,那么该类会默认继承Object类。
常用方法:
也可以重写这些方法!
5.16 异常
5.16.1 try....catch
异常捕获:try...catch 需要经验,程序可以继续往下走
public class Example25 {
public static void main(String[] args) {
//下面的代码定义了一个try…catch语句用于捕获异常
try {
int result = divide(4, 0); //调用divide()方法
System.out.println(result);
} catch (Exception e) { //对异常进行处理
System.out.println("捕获的异常信息为:" + e.getMessage());
}
System.out.println("程序继续向下执行...");
}
try...catch和finally
try有问题 进catch往下执行,遇到return执行但是finally必须执行。释放资源用于 释放堆内存,因为不会自己释放
1 public class Example26 {
2 public static void main(String[] args) {
3 //下面的代码定义了一个try…catch…finally语句用于捕获异常
4 try {
5 int result = divide(4, 0); //调用divide()方法
6 System.out.println(result);
7 } catch (Exception e) { //对捕获到的异常进行处理
8 System.out.println("捕获的异常信息为:" + e.getMessage());
9 return; //用于结束当前语句
10 } finally {
11 System.out.println("进入finally代码块");
12 }
13 System.out.println("程序继续向下执行…");
14 }
15 //下面的方法实现了两个整数相除
16 public static int divide(int x, int y) {
17 int result = x / y; //定义一个变量result记录两个数相除的结果
18 return result; //将结果返回
19 }
20 }
不论程序是发生异常还是使用return语句结束,finally中的语句都会执行。因此,在程序设计时,通常会使用finally代码块处理完成必须做的事情,如释放系统资源。
System.exit(0)表示退出当前的Java虚拟机,Java虚拟机停止了,任何代码都不能再执行了。
5.17 throws 关键字(遇到后续要重新编译!)
会经常那个遇到:!!!
并不知道别人编写的方法是否会发生异常。针对这种情况,Java允许在方法的后面使用throws关键字对外声明该方法有可能发生的异常,这样调用者在调用方法时,就明确地知道该方法有异常,并且必须在程序中对异常进行处理,否则编译无法通过。
包起来: