Java-面向对象
1、面向对象 & 面向过程
- 面向过程
步骤清晰简单,第一步做什么,第二步做什么… 就像是你今天中午要炒菜,炒一个鸡蛋西红柿,第一步,洗西红柿,切西红柿,第二步打鸡蛋,第三步放点盐,第四步,开火,放油… 一步一步来。
面向过程去处理这种一系列较为简单的问题。
- 面向对象
- 物以类聚,分类的思维模式,思考问题首先回解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。比如你炒菜需要分类:素菜和荤菜,把类实例化一个对象.素菜今天的实例对象是鸡蛋西红柿,麻辣豆腐。然后才对具体对象 菜的做饭进行面向过程的探索
- 面向对象适合处理复杂的问题,适合处理需要多人协作的问题!
- 对于复杂的事物,我们需要用面向对象的思路在宏观上分析整个系统。 对于细微之处,仍然需要面向过程的思路去处理。
那么什么是面向对象?
- 面向对象编程(Object-Oriented Programming.OOP)
- 面向对象编程的本质就是:以类的方式组织代码,以对象的形式组织(封装)数据。
1.2、类和对象的关系
类是一种抽象的数据类型,它是对某一类事物整体的定义, 但是不能代表某一个具体的事物。比如素菜、荤菜、川菜、湘菜…
对象是 抽象的类这个概念 的 一个具体实例。比如:鸡蛋西红柿就是 素菜的一个具体实例; 剁椒鱼头就是湘菜的一个具体实例。
Java 语言是面向对象的:Java 语言提供类、接口和继承等面向对象的特性,为了简单起见,只支持类之间的单继承(extends),但支持接口之间的多继承,并支持类与接口之间的实现机制(关键字为 implements)
对象是根据类创建的。在Java中,使用关键字 new 来创建一个新的对象。创建对象需要以下三步:
- 声明:声明一个对象,包括对象名称和对象类型。
- 实例化:使用关键字 new 来创建一个对象。
- 初始化:使用 new 创建对象时,会调用构造方法初始化对象。
下面是一个创建对象的例子:
public class Puppy{
public Puppy(String name){
//这个构造器仅有一个参数:name
System.out.println("小狗的名字是 : " + name );
}
public static void main(String[] args){
// 下面的语句将创建一个Puppy对象
Puppy myPuppy = new Puppy( "tommy" );
}
}
1.3、创建和初始化对象
- 使用new关键字创建对象。 前面的创建一个数组也是 new 新建一个。
- 使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。
- 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:
- 必须和类的名字相同
- 必须没有返回类型,也不能写void
关于构造器,即构造方法的解释, java默认创建的构造方法,我在前面有解释。
构造器详解:
- 使用new 关键字,本质在调用构造方法
- 用来初始化对象的值
注意点:
- 定义有参构造之后,如果想使用无参构造,要显示定义一个无参的构造。
快捷键 alt+Insert 生成 构造器。
1.3.1、抽象的类 实例化一个 对象
例子:定义一个学生类, 这个 class Student 的属性有name, age。 他是抽象的, 就好比 人 是一个抽象的 class。它不是一个具体的对象。
public class Student {
//定义属性
String name;
int age;
// study() 方法
//this.属性 表示当前的属性
public void study(){
System.out.println(this.name+"学习快乐!");
}
}
student 类实例化, 生成一个具体的对象,比如鑫仔 就是一个具体存在的 class Student。 鑫仔就是一个具体的人, 人是抽象的存在。 将 class Student 实例化, 创建具体的对象,如鑫仔,
//一个项目应该只有一个main 方法
public class Application {
public static void main(String[] args) {
//类: 抽象的
//将类实例化后 就会返回一个当前的 自己的对象
//student对象就是 类 Student实例化后一个具体的实例!
Student student = new Student();
Student xin = new Student(); //类Student,实例化一个具体的对象 xin
xin.name = "鑫仔";
xin.age = 18;
System.out.println(xin.name);
System.out.println(student.name);
System.out.println(xin.age);
System.out.println(student.age);
xin.study();
}
}
结果为:
鑫仔
null
18
0
鑫仔学习快乐!
上述的代码含义表示的就是:
以类的方式去组织代码,形成一个个类; 类中有不同的属性;
然后以对象的形式去封装数据。 每个对象的属性有着具体值。
1.3.2、构造器详解
每个类都有一个构造器,你不定义的时候,会有一个默认的构造方法。构造方法的修饰符和名字必须与类相同。
当你创建一个类,对类实例化一个 具体对象时, 即采用new关键字, 实际上你就在调用它的构造器了。这个构造器是用来初始化值的。
例子:
public class Person02 {
//一个类即使什么都不写,它也会存在一个方法
//显示的定义构造器
String name;
//实例化初值
// 当使用new关键字时,本质就是在调用构造器
public Person02(){ // 这个就是显示定义的构造器, 名字和修饰符必须要与类Person2一样
this.name = "ALZN";
}
//有参构造,一旦定义了有参构造,无参就必须要显示定义
public Person02(String name) {
this.name = name;
}
}
public class Application02 {
public static void main(String[] args){
//new 实例化一个对象。 就相当于调用了 类Person2 的构造器
Person02 person02 = new Person02();
System.out.println(person02.name); //结果为 ALZN
}
}
我们可以发现,在Application02 中运行main方法时, 结果输出 ALZN, 但我们并没有赋值, 这是因为new 已经调用了构造器。
1.4、类与对象总结
- 类与对象
类是一个模板:抽象的;对象是一个具体的实例 - 方法:定义、调用!
- 对应的引用
引用型:基本类型(8种)
对象是通过引用来操作的:栈---->堆 - 属性:字段Field成员变量
默认初始化:数字: 0 0.0; char:u0000; boolean:false; 引用 null - 对象的创建和使用:
- 必须使用new 关键字创造对象,构造器Person person=new Person();
- 对象的属性person.name
- 对象的方法person.sleep();
- 类:
- 静态的属性 属性
- 动态的行为 方法
2、封装
- 程序设计要追求“高内聚,低耦合”
- 应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,称为信息隐藏。
记住这句重点:属性私有,get/set。
封装一般是去针对 属性去做的。private/public 这两个修饰词来决定。
封装之后,为了获得属性,需要去采用get/set 这两种方法去定义一个公共的属性, 采用alt+insert 快捷键可以去定义get/set 的公共属性。
例子: 类中的属性私有 即封装, 则创建的具体对象 就不能获得,继承这些属性, 需要定义get/set 的公共属性
public class NewPerson1 {
//属性私有
private String name;
private int age;
//采用 ALT+INSERT 快捷键,来 get/set得到这些私有的属性
// 创建一个公共属性
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 ApplicationNewPerson {
public static void main(String[] args) {
//new 实例化一个对象
NewPerson1 newPerson = new NewPerson1();
newPerson.setAge(18);
newPerson.setName("ALZN");
System.out.println(newPerson.getAge());
System.out.println(newPerson.getName());
}
}
结果:只有这样,才能继承 NewPerson1 的属性。
18
ALZN
3、继承
继承
- 本质是对某一批类的抽象,从而实现对现实世界更好的建模;
- extands意思是“扩展”。子类是父类的扩展;
- java中类只有单继承,没有多继承!
- 继承是类和类之间的一种关系,除此之外,类和类之间的关系还有依赖,组合,聚合等
- 继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends表示
- 子类和父类之间从意义上将应该具有“is a”的关系
父类扩展了一个子类, 子类 extends。 子类继承了父类的所有东西,比如方法, 属性
例子:父类:
public class Person1 {
//人: 父类
public int money= 10_0000_0000; //属性: money
protected String name = "AL";
//私有属性 age
private int age = 40;
public void say(){
System.out.println("你好啊!");
}
//利用快捷键 ALT+ INSERT创建公共属性
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
子类:
//学生 是 人: 派生类,子类
// 采用 extends,表示父类的扩展 扩展为子类 student01
public class Student01 extends Person1{
//子类继承了父类,虽然子类中没有定义,
// 但会继承父类的全部 属性 和 方法
private String name = "ZN";
public void test(String name){
System.out.println(name); //ALZN
System.out.println(this.name); //ZN 本身调用者,当前对象的
System.out.println(super.name);// AL. super,用于调用父类的
}
}
测试:
public class Application01 {
public static void main(String[] args) {
// new 创建了一个新的子类 Student01, 子类变量名字为student01
Student01 student01 = new Student01();
System.out.println(student01.money); //继承了属性money
student01.say(); //继承了方法 say().
System.out.println(student01.getAge()); //继承公共属性
student01.test("ALZN");
}
}
测试的结果为:
1000000000
你好啊!
40
ALZN
ZN
AL
结果表明:
- student01 是 对类Student01 实例化后的一个具体对象。
- 子类Student01 会继承父类的属性和方法,
- 但是父类的私有属性,必须要使用get/set 去建立公共的属性,子类才能继承。
- 需要注意的是 this 和 super。 this.name:本身调用者,当前对象的,这里是student01在test方法中测试时,在类Student01中调用,当前对象,即这段代码在Student01 中,它的name是ZN。super,用于调用父类的
super注意点:
- super调用父类的构造方法,必须在构造方法的第一个
- super只能出现在子类的方法或者构造方法中!
- super和this不能同时调用构造方法!
this:代表的对象不同:
- this:本身调用者这个对象
- super:代表对 父类对象的引用
前提
- this:没有继承也可以使用
- super:只能在继承条件才可以使用
构造方法
- this()本类的构造
- super()父类的构造
4、方法重写
重写:需要有继承关系,子类重写父类的方法!
- 方法名必须相同
- 参数列表必须相同
- 修饰符:范围可以扩大但不可以缩小:public>protected>Default>private
- 抛出的异常:范围,可以被缩小,但不能扩大:ClassNotFoundException—>Exception(大)
重写:子类的方法和父类必须要一致!方法体不同!
为什么需要重写:父类的功能,子类不一定需要,或者不一定满足!
快捷键:Alt+Insert: override
例子:关于方法重写:
public class TestOverride {
public static void main(String args[]){
Animal a = new Animal(); // Animal 对象
Animal b = new Dog(); // Dog 对象
a.move();// 执行 Animal 类的方法
b.move();//执行 Dog 类的方法
}
}
class Animal{
public void move(){
System.out.println("动物可以移动");
}
}
class Dog extends Animal{
public void move(){
System.out.println("狗可以跑和走");
}
}
结果为:
动物可以移动
狗可以跑和走
重写与重载之间的区别
区别点 | 重载方法 | 重写方法 |
参数列表 | 必须修改 | 一定不能修改 |
返回类型 | 可以修改 | 一定不能修改 |
异常 | 可以修改 | 可以减少或删除,一定不能抛出新的或者更广的异常 |
访问 | 可以修改 | 一定不能做更严格的限制(可以降低限制) |
5、多态
多态:即同一方法可以根据发送对象的不同而采用多种不同的行为方式。
一个对象的实际类型是可以确定的,但可以指向对象的引用的类型有很多。
多态存在的条件:
- 有继承关系
- 子类重写父类方法
- 父类引用指向子类对象
注意:多态是方法的多态,属性没有多态性。
instanceof 引用类型类型转换。(下面会讲)
父类和子类,有联系,类型转换异常!ClassCastException!
不能重写方法:
1.static方法,属于类,不属于实例
2.final常量
3.private方法
5.1、instanceof和类型转换
instanceof(类型转换) 引用类型, 去判断一个对象是什么类型。
instanceof 严格来说是Java中的一个双目运算符,用来测试一个对象是否为一个类的实例。
5.2、static关键字详解
有static时,直接在类下面定义的属性为静态属性;没有static就是非静态属性。
静态属性可以由类 class 也可以由方法直接去引用, 但是非静态属性只能由方法去引用。
例子:
//static
public class Student02 {
private static int age; //静态的变量 多线程
private double score;
public void run(){
}
public static void main(String[] args){
Student02 s2 = new Student02();
System.out.println(Student02.age);
System.out.println(s2.age);
System.out.println(s2.score);
}
}
static方法也是类似。
5.3、抽象类
- abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,name该方法就是抽象方法,如果修饰类,该类就是抽象类。
- 抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类
- 抽象类,不能使用new关键字来创建对象,它是用来让子类继承
- 抽象方法,只有方法的声明,没有方法的实现,是用来让子类实现的
- 子类继承抽象类,那么久必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。
5.4、接口
普通类:只有具体实现
抽象类:具体实现和规范(抽象方法)都有!
接口:只有规范!自己无法写方法~专业的约束!约束和实现分离:面向接口编程!!!
接口就是规范,接口的本质是契约!!
声明类的关键字是class,声明接口的关键字是interface
作用
- 接口是一个约束
- 定义一些方法,让不同的人实现
- 方法只能创建抽象,创建 public sbstract
- 属性只能创建常量,常量创建 public static final
- 接口不能被实例化,接口中没有构造方法
- implements 可以实现多个接口
- 必须要重写接口中的方法
接口有多继承, 类只有单继承。
Java 语言提供类、接口和继承等面向对象的特性,为了简单起见,只支持类之间的单继承,但支持接口之间的多继承,并支持类与接口之间的实现机制(关键字为 implements)。
单继承:
Java 不支持多继承,只允许一个类直接继承另一个类,即子类只能有一个父类,extends 关键字后面只能有一个类名。例如,如下代码会导致编译错误:
class Student extends Person,Person1,Person2{…}
class Student extends Person,extends Person1,extends Person2{…}
尽管一个类只能有一个直接的父类,但是它可以有多个间接的父类。例如,Student 类继承 Person 类,Person 类继承 Person1 类,Person1 类继承 Person2 类,那么 Person1 和 Person2 类是 Student 类的间接父类。
多继承: 对于接口来讲,可以继承多个接口哦:
class Student implements Person,Person1,Person2{…}
class Student implements Person,extends Person1,extends Person2{…}
5.5、内部类
- 内部类
内部类就是在一个类的内部再定义一个类,如,A类中定义B类,B类就是A类的内部类;反之,A类是B类的外部类。 - 成员内部类:在类的里面写一个类
- 静态内部类:在类的里面写一个stiatic修饰的类
- 局部内部类:在类的方法里面写一个类
- 匿名内部类