目录
一、类与对象的关系
(1)类是一种抽象的数据类型,他是对某一类事物整体描述/定义,但并不能代表某一个具体的事物。
如动物、植物、手机、电脑...
Person类、Pet类等这些类都是用来描述/定义某一类具体的事物应该具备的特点和行为
(2)对象是抽象概念的具体实例
张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例。
能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念。
二、什么是面向对象
面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据
三大特性:封装、继承、多态
三、构造方法与对象的创建、封装详解
3.1创建与初始化对象
创建一个对象包括对象的声明和为对象分配变量两个步骤。
①对象的声明
一般格式为:类的名字 对象名字;
例如:Lader lader;
②为声明的对象分配变量
使用new运算符和类的构造方法为声明的对象分配变量,即创建对象。
如下:使用new关键字创建对象
//Application.java:
public class Application {
public static void main(String[] args) {
//类:抽象的,实例化
//类实例化后会返回一个自己的对象
Student xiaoming = new Student();
xiaoming.name="小明";
xiaoming.age=10;
System.out.println(xiaoming.name);
System.out.println(xiaoming.age);
new Student().study();
}
}
//Student.java:
public class Student {
//属性:字段
String name;
int age;
//方法:
public void study(){
System.out.println("在学习");
}
}
运行截图:
3.2构造方法
类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。类中的构造方法的名字必须与它所在的类的名字完全相同,而且没有类型。允许在一个类中编写若干个构造方法,但必须保证他们的参数不同。参数不同是指:参数的个数不同,或者参数的个数相同,但参数列表中对应的某个参数的类型不同。
总结一下,构造器有以下两大特点:
(1)必须和类的名字相同
(2)必须没有返回类型,也不能写void
//Application.java:
public class Application {
public static void main(String[] args) {
Person person = new Person("喵酱");
System.out.println(person.name);
}
}
//Person.java:
public class Person {
//一个类即使什么都不写,也会存在一个方法
//显示的定义构造器
String name;
//实例化初始值
//1.使用new关键字,本质实在调用构造器
//2.用来初始化值
public Person(){
}
//有参构造:一旦定义了有参构造,无参就必须显示定义
public Person(String name){
this.name=name;
}
}
运行截图:
总结就是:
构造器和类名相同,没有返回值。
作用:1、new本质再调用构造方法 2、 初始化对象的值
注意点:定义有参构造之后,如果想使用无参构造,显示的定义一个无参的构造
快捷键:alt+insert
3.3使用对象
通过使用运算符“.”,对象可以实现对自己的变量的访问和方法的调用
①对象操作自己的变量(体现对象的属性)
对象创建之后,就有了自己的变量,即对象的实体。对象通过使用点运算符“.”(点运
算符也称引用运算符或访问运算符)访问自己的变量,访问格式为:
对象.变量;
②对象调用类中的方法(体现对象的行为)
对象创建之后,可以使用点运算符“”调用创建它的类中的方法,从而产生一定的行为
(功能),调用格式为:
对象.方法;
③ 体现封装
当对象调用方法时,方法中出现的成员变量就是指分配给该对象的变量。类中的方法可以操作成员变量。当对象调用方法时,方法中出现的成员变量就是指分配给该对象的变量。
封装案例如下:
//Student.java
public class Student {
//private 私有
//属性私有
private String name; //姓名
private int age; //年龄
private char sex; //性别
//提供一些可以操作这个属性的方法 快捷键:alt+insert
//提供一些public的get、set方法
//get 获得这个数据
public String getName() {
return name;
}
//set 给这个数据设置值
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
}
//Application.java
public class Application {
public static void main(String[] args) {
Student stu1 = new Student();
stu1.setName("喵酱");
stu1.setAge(22);
stu1.setSex('女');
System.out.println(stu1.getName());
System.out.println(stu1.getAge());
System.out.println(stu1.getSex());
}
}
运行截图如下:
封装的好处:
(1)提高程序的安全性,保护数据
(2)可以隐藏代码的实现细节
(3)统一接口
(4)增加系统的可维护性
代码举例如下:
//在Student类中对年龄设置限制
public void setAge(int age) {
if (age>120 || age<0){
//年龄不合法
this.age=2;
}
else{
this.age=age;
}
}
//Application类中检验
Student stu2 = new Student();
stu2.setAge(-1); //不合法的年龄
System.out.println(stu2.getAge());//将输出2
运行截图:
总结封装一句话:属性私有,get/set
四、继承
继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
extends的意思是“扩展”。子类是父类的扩展。
Java中类只有单继承,没有多继承。
继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示。
格式如下:
class 子类名 extends 父类名{
...
}
//举例
class Student extends People{
...
}
五、Super与this
super注意点:
1.super调用父类的构造方法,必须在构造方法的第一个
2.super 必须只能出现在子类的方法或者构造方法中
3.super和 this 不能同时调用构造方法!
与this相比:
1.代表的对象不同:
this:本身调用着这个对象
super:代表父类对象的引用
前提
this:没有继承也可以使用
super:只能在继承条件下才可以使用
构造方法
this():本类的构造
super():父类的构造
六、方法重写
子类通过重写可以隐藏已继承的方法(方法重写称为方法覆盖)
①重写的语法规则
如果子类可以继承父类的某个方法,那么子类就有权利重写这个方法。所谓方法重写,是指子类中定义一个方法,这个方法的类型和父类的方法的类型一致或者是父类的方法的类型的子类型(所谓子类型,是指如果父类的方法的类型是 “类”,那么允许子类的重写方法的类型是“子类”),并且这个方法的名宇、参数个数、参数的类型和父类的方法完全相同。子类如此定义的方法称作子类重写的方法。
② 重写的目的
子类通过方法的重写可以隐藏继承的方法,子类通过方法的重写可以把父类的状态和行为改变为自身的状态和行为。如果父类的方法f()可以被子类继承,子类就有权重写 f(),一旦子类重写了父类的方法f(),就隐藏了继承的方法f(),那么子类对象调用方法 f()一定调用的是重写方法f();如果子类没有重写,而是继承了父类的方法f(),那么子类创建的对象当然可以调用 f()方法,只不过方法f()产生的行为和父类的相同而己。
重写方法既可以操作继承的成员变量、调用继承的方法,也可以操作子类新声明的成员变量、调用新定义的其他方法,但无法操作被子类隐藏的成员变量和方法。如果子类想使用被隐藏的方法或成员变量,必须使用关键字 super。
简单代码演示:
//Application.java
public class Application {
public static void main(String[] args) {
//静态方法中:方法的调用只和左边定义的数据类型有关
//非静态方法中:重写
A a = new A();
a.test(); //A
//父类的引用指向了子类A
B b = new A(); //子类重写了父类的方法
b.test(); //B
}
}
//A.java
//继承
public class A extends B{
//Override 重写
@Override
public void test() {
System.out.println("A----test");
}
}
//B.java
//重写是方法的重写 与属性无关
public class B {
public void test(){
System.out.println("B----test");
}
}
运行结果:
总结:
重写:需要有继承关系,子类重写父类的方法
1.方法名必须相同
2.参数列表列表必须相同
3.修饰符:范围可以扩大但不能缩小:public>Protected>Default>private
4.抛出的异常:范围,可以被缩小,但不能扩大:
ClassNotFoundException---->Exception(大)
重写,子类的方法和父类必要一致;方法体不同
为什么需要重写:
1. 父类的功能,子类不一定需要,或者不一定满足
快捷键:Alt + Insert
七、多态
即同一方法可以根据发送对象的不同而采用多种不同的行为方式
一个对象的实际类型是 可以确定的,但可以指向对象的引用类型有很多
//Student.java
public class Student extends Person {
@Override
public void run() {
System.out.println("son");
}
public void eat(){
System.out.println("eat");
}
}
//Person.java
public class Person {
public void run(){
System.out.println("run");
}
}
//Application.java
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
//new Student();
//new Person();
//可以指向的引用类型就不确定了,父类的引用指向子类
Student s1 = new Student(); //Student能调用的方法都是自己的或者继承父类的
Person s2 = new Person(); //Person父类型,可以指向子类,但是不能调用子类独有的方法
Object s3 = new Student();
//对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
s2.run();//子类重写了父类的方法,执行子类的方法
s1.run();
System.out.println("--------------------");
//s2.eat();
s1.eat();
}
}
执行结果:
总结:
1.多态是方法的多态,属性没有多态
2.父类和子类,有联系,类型转换异常(ClassCastException)
3.存在条件:继承关系,方法需要重写,父类引用指向子类对象。(Father f1=new Son();)
4.不能使用多态的:
①static方法属于类,不属于实例
②final 常量
③private方法
八、instanceof和类型转换
(学的有点懵)
1.向上转型
从子到父
父类引用指向子类对象
2.向下转型
从父到子
父类引用转为子类对象
//Application.java
public class Application {
public static void main(String[] args) {
/*编译看左边 运行看右边
* 1.向上转型
从子到父
父类引用指向子类对象
2.向下转型
从父到子
父类引用转为子类对象
*/
//类型之间的转化:父 子
//高 低
Person s1=new Student(); //向上转型
//student 将这个对象转换为Student类型,我们就可以使用Student类型的方法
Student student=(Student) s1; //向下转型
student.go();
//子类转换为父类,可能丢失自己的本来的一些方法
Student stu1=new Student();
stu1.go();
Person per=stu1;
}
}
注意:
① 不要将父类创建的对象和子类对象的上转型对象混淆。
② 可以将对象的上转型对象再强制转换到一个子类对象,这时,该子类对象又具备
了子类所有的属性和功能
③ 不可以将父类创建的对象的引用赋值给子类声明的对象(不能说“人是美国人”)。
④ 如果子类重写了父类的静态方法,那么子类对象的上转型对象不能调用子类重写
的静态方法,只能调用父类的静态方法
九、抽象
1.用关键字abstract修饰的类称为abstract类(抽象类),例如:
abstract class A{
...
}
2.用关键字abstract修饰的方法称为abstract方法 (抽象方法),例如:
abstract int min (int x,int y);
对于abstract方法,只允许声明,不允许实现(没有方法体),且不允许使用final和abstract同时修饰一个方法或类,也不允许使用static修饰abstract方法,即abstract方法必须是实例方法。
①abstract 类中可以有abstract 方法
和普通类(非abstract 类)相比,abstract 类中可以有abstract 方法(非abstract 类中不可
以有abstract 方法),也可以有非abstract 方法。
下面的 A类中的 min()方法是 abstract 方法,max()方法是普通方法(非abstract 方法)。
abstract class A {
abstract int min(int x,int y);
int max (int x, int y) {
return x›y?x:y;
}
}
//注:abstract 类里也可以没有abstract 方法。
② abstract 类不能用new 运算符创建对象
对于 abstract 类,我们不能使用 new 运算符创建该类的对象。如果一个非抽象类是某个抽象类的子类,那么它必须重写父类的抽象方法,给出方法体,这就是为什么不允许使用 final和abstract 同时修饰一个方法或类的原因。
③ abstract 类的子类
如果一个非 abstract 类是abstract 类的子类,它必须重写父类的 abstract 方法,即去掉
abstract 方法的 abstract 修饰,并给出方法体。如果一个abstract 类是abstract 类的子类,它可
以重写父类的 abstract 方法,也可以继承父类的 abstract 方法。
④ abstract 类的对象作上转型对象
可以使用 abstract 类声明对象,尽管不能使用 new 运算符创建该对象,但该对象可以成为其子类对象的上转型对象,那么该对象就可以调用子类重写的方法。