面向对象(OO,Object Oriented)与面向过程(PO,Procedure Oriented):面向过程是一种编程思想,它强调的是过程,意思是我们做任何事,都需要亲力亲为。面向对象会把事物抽象成对象的概念,先抽象出对象,然后给对象赋一些属性和方法,然后让每个对象去执行自己的方法
1.什么是类?什么是对象
对象:软件中真实存在的单个的个体/东西,现实生活是由很多很多对象组成的,基于对象抽 出了类
类:类型/类别,是一种引用的数据类型,Java语言最基本单位就是类,类是一类事物抽取共 同属性与功能形成的
-
类中可以包含:
-
对象的属性/特征/数据----------------------成员变量
-
对象的行为/动作/功能----------------------方法
-
类和对象的关系
1)我们先创建类,再通过类创建出对象
2)我们可以通过一个类创建出多个对象
3)类是抽象的,对象是具体的
OOA:面向对象分析 - OOD:面向对象设计 - OOAD:面向对象分析与设计 -OOP:面向对象编程
创建对象
案例
数据类型 引用类型变量 指向 对象
Student ll = new Student();
默认值规则:
byte,short,int,long,char---------------0 float,double---------------------------0.0 boolean--------------------------------false 引用类型---------------------------------null
2.面向对象的特征
1)封装: 把相关的数据封装成一个“类”组件
2)继承: 是子类自动共享父类属性和方法,这是类之间的一种关系
3)多态: 增强软件的灵活性和重用性
3.this关键字
this:指代当前对象,哪个对象调用方法它指的就是哪个对象
只能用在方法中,方法中访问成员变量之前默认有个this.
- this的用法:
- this.成员变量名--------------------访问成员变量
当成员变量与局部变量同名时,若想访问成员变量,则this不能省略(主要用法)
- this.方法名()-------------------------调用方法(一般不用)
- this()-----------------------------------调用构造方法(一般不用)
示例:
public class Car { String brand; // 汽车品牌 String color; // 汽车颜色 double price; // 汽车价格 // 空构造函数,不带参数 Car(){}; /* * 带参数的构造函数,用于初始化汽车的品牌、颜色和价格。 * @param brand 汽车品牌 * @param color 汽车颜色 * @param price 汽车价格 */ Car(String brand,String color,double price) { this.brand=brand; this.color=color; this.price=price; }}
4.构造方法
构造方法:构造函数、构造器、构建器----------好处:复用给成员变量赋初始值的代码
- 作用:给成员变量赋初始值
- 语法:与类同名,没有返回值类型(连void都没有)
类名(参数){方法体}
- 调用:在创建(new)对象时被自动调用
- 若自己不写构造方法,则编译器默认提供一个无参构造方法,若自己写了构造方法,则不 再默认提供,默认的无参构造会被覆盖,注意要手动添加
- 构造方法可以重载
5.继承
- 作用:代码复用
- 通过extends实现继承
- 超类/基类/父类:共有的属性和行为
派生类/子类:特有的属性和行为
- 派生类可以访问:超类的+派生类的,超类不能访问派生类的
- 一个超类可以有多个派生类,一个派生类只能有一个超类---------单一继承
- 具有传递性
- java规定:构造派生类之前必须先构造超类
- 在派生类的构造方法中若没有调用超类的构造方法,则默认super()调用超类的无参构造方法
- 在派生类的构造方法中若自己调用了超类的构造方法,则不再默认提供
> 注意:super()调用超类构造方法,必须位于派生类构造方法中的第1行
1) 泛化:从程序设计角度而言叫泛化,从代码实现角度而言叫继承,泛化就是继承
2) 继承要符合is(是)的关系
3) 继承的是父类的成员变量和普通方法,不包括构造方法,父类的构造方法是被子类通过 super来调用的
super关键字
super:指代当前对象的超类对象
- super.成员变量名-------------------------访问超类的成员变量
> 当超类成员变量和派生类成员变量同名时,super指超类的,this指派生类的
> 若没有同名现象,则写super和this是一样的
- super.方法名()------------------------------调用超类的方法
- super()----------------------------------------调用超类的构造方法
final关键字
final:最终的、不能改变的
- 修饰变量:变量不能被改变
- 修饰方法:方法不能被重写
- 修饰类:类不能被继承
6.方法的重写(override/overriding):重新写、覆盖
-
发生在父子类中,方法名相同,参数列表相同
-
重写方法被调用时,看对象的类型---------------new谁就调谁的
-
重写与重载的区别:
-
重写(overriding):发生在父子类中,方法名相同,参数列表相同
-
重载(overloading):发生在同一类中,方法名相同,参数列表不同
-
7.抽象abstract
1). 抽象方法:
- 由abstract修饰
- 只有方法的定义,没有具体的实现(连{}都没有)
2) 抽象类:
- 由abstract修饰
- 包含抽象方法的类必须是抽象类,但不包含抽象方法的类也可以声明为抽象类
- 抽象类不能被实例化(new对象)
- 抽象类是需要被继承的,派生类:
- 必须重写所有抽象方法
- 也声明为抽象类----------------------------一般不这么用
抽象类的意义:
- 封装共有的属性和行为------------------代码复用
- 可以包含抽象方法,为所有派生类统一入口(名字统一),强制必须重写
8.接口interface
- 是一种引用数据类型
- 由interface定义
- 只能包含抽象方法(常量、默认方法、静态方法、私有方法)
- 接口不能被实例化,不能new对象
- 接口是需要被实现/继承的-------实现类/派生类:必须重写接口中的所有抽象方法
- 注意:重写接口中的方法时,必须加public
- 一个类可以实现多个接口,用逗号分隔。若又继承又实现时,应先继承后实现
- 接口可以继承接口,可以继承多个
类间关系:
- 类和类-------------------------------继承
- 接口和接口-------------------------继承
- 类和接口----------------------------实现
9.设计规则
- 将所有派生类共有的属性和行为,抽到超类中-------------抽共性
- 若派生类的行为/代码都一样,设计普通方法
若派生类的行为/代码不一样,设计抽象方法
- 将部分派生类共有的行为,抽到接口中
- 接口对继承单根性的扩展------------------------实现多继承
- 接口是一种标准、规范,若实现了某接口就具备某个功能,若不实现接口就不具备那 个功能
10.多态
多态是面向对象程序设计(OOP)的一个重要特征,指同一个实体同时具有多种形式,即 同一个对象,在不同时刻,代表的对象不一样,指的是对象的多种形态。
1.多态的优点
1)多态可以让我们不用关心某个对象到底具体是什么类型,就可以使用该对象的某些方法
2)将父类作为参数或返回值类型,传递或返回子类对象,以扩大方法的应用范围,实现 代码复用提高了程序的可扩展性和可维护性,实现代码的复用
2.向上造型(自动类型转换)
1)向上转型:可以把不同的子类对象都当作父类来看,进而屏蔽不同子类对象之间的 差异,写出通用的代码,做出通用的编程,统一调用标准
2)父类的引用指向子类的对象
3)向上转型时,子类对象当成父类对象,只能调用父类的功能,如果子类重写了父类 中声明过的方法,方法体执行的就是子类重过后的功能。但是此时对象是把自己看 做是父类类型的,所以其他资源使用的还是父类型的
3.向下造型(强制转换类型)
1)-引用所指向的对象,就是该类型
-引用所指向的对象,实现了该接口或继承了该类
2)案例:
Animal为父类 ,dog是其子类,Swim是dog实现的接口
Animal all= new Dog();
Dog g= (Dog) all;//引用所指向的对象,就是该类型
Swim s=(Swim)all;//引用所指向的对象,实现了该接口或继承了该类
3) 强转之前先通过instanceof来判断引用的对象是否是该类型
注意:强转时若不符合如上条件,则发生ClassCastException类型转换异常
示例:
Animal all= new Dog(); Dog g= (Dog) all; Swim s=(Swim)all; if (all instanceof Dog){ Dog gg=(Dog) all; } if (all instanceof Swim){ Swim ss=(Swim) all; }
11.成员内部类
-
类中套类,外面的称为外部类,里面的称为内部类
-
内部类通常只服务于外部类,对外不具备可见性
-
内部类对象通常在外部类中创建
-
内部类可以直接访问外部类的成员,在内部类中有个隐式的引用指向创建它的外部类对象
隐式的引用:外部类名.this
-
何时用:若A类只让B类用,并且A类还想访问B类的成员时,可以设计成员内部类
-
案例
class Aa{ //外部类
String name;
void show1(){
Bb b = new Bb();
}
class Bb{ //成员内部类
void show2(){
System.out.println(name); //简写
System.out.println(Aa.this.name); //完整写法,Aa.this指代外部类对象
}
}
12.匿名内部类
1)案例
class A{
public static void main(String[] args) {
//a)创建了Inter的一个派生类,但是没有名字
//b)为该派生类创建了一个对象,名为o1,向上造型为Inter类型
// ----new Inter(){};是在创建Inter的派生类的对象
//c)大括号中的为派生类的类体
Inter o1 = new Inter(){};}
}
interface Inter(){}
2)什么是匿名内部类:匿名内部类是 Java 编程语言中一种特殊的类,它没有显式地定义类名, 而是在创建对象时通过传递实现了某个接口或继承了某个类的代码块来定义类。
3)匿名内部类的优点:我们使用它来简化代码、减少类的数量和更高效地编写事件处理程序等.
4)何时用:若想创建一个派生类的对象,并且对象只创建一次,可以设计为匿名内部类,可以大 大简化代码.
5)注意:匿名内部类中不能修改外面局部变量的值
6)问:内部类有独立的.class吗?
答: 会,匿名内部类编译后会生成class文件,名称是类名$+1,2,3.....class文件
13.封装
1)封装是隐藏对象的属性和实现细节,仅仅对外提供公共的访问方式,比如类和方法
2)优点:a提高安全性b提高重用性
3)问:如何封装?封装后的资源如何访问?
答:我们可以使用private关键字来封装成员变量与方法,使用getset方法访问
如何访问私有资源?
关于成员变量:
setXxx – 对外提供公共的设置值方式
getXxx – 对外提供公共的获取值方式
关于成员方法:
把私有方法放在公共方法里供外界调用即可
4)访问控制修饰符:--------------保护数据的安全(隐藏数据、暴露行为),实现封装
- public:公开的,任何类(主要)
- private:私有的,本类(主要)
- protected:受保护的,本类、派生类、同包类
- 默认的:本类、同包类
> 注意:a.访问权限由低到高依次为:private<默认的<protected<public
b.类的访问权限只能是public或默认的,类中成员的访问权限如上4种都可以。
14.static:静态的
1)修饰变量--静态变量
-由static修饰 static 类型 类名
- 属于类,存储在方法区中,只有一份
- 常常通过类名点来访问
- 何时用:对象所共享的数据
成员变量分两种:
- 实例变量:没有static修饰,属于对象的,存储在堆中,有几个对象就有几份,通过 引用对象打点来访问
- 静态变量:有static修饰,属于类的,存储在方法区中,只有一份,通过类名打点来 访问
注意:static final常量
- 必须声明同时初始化
- 常常通过类名点来访问,不能被改变
- 常量名所有字母都大写,多个单词之间用_分隔
- 优点:编译器在编译时,会将常量直接替换为具体的数,效率高
- 何时用:在程序运行过程中数据永远不变,并且经常使用
2)静态块:
- 由static修饰 static{ System.out.println("静态块");}
- 属于类,在类被加载期间自动执行,一个类只被加载一次,所以静态块也只执行一次
- 何时用:初始化/加载静态资源/静态变量
3)修饰方法-----静态方法:
- 由static修饰
- 属于类,存储在方法区中,只有一份
- 常常通过类名点来访问
- 静态方法中没有隐式this传递,所以静态方法中不能直接访问实例成员(实例变量/实例方法)
- 何时用:方法的操作与对象无关(不需要访问对象的属性/行为){在方法中不需要访问对象1 的属性/行为,所以认为方法的操作与对象无关,可以设计为静态方法}
15.枚举
- 是一种引用数据类型(还有类class,数组arry,接口interfce)
- 特点:枚举类型的对象数目是固定的,常常用于定义一组常量,放在代码块第一行
- 枚举的构造方法都是私有的
- 所有枚举都继承自Enum类,其中提供了一组方法供我们使用
-使用 enum 关键字来定义,各个常量使用逗号 , 来分割。枚举类和正常类一样,也可以成员 变量、实例方法、静态方法、抽象方法。
案例:
/**
* 季节枚举类,定义了一年四季及其特点。
*/
public enum Seasons {
SPRING("春天","暖和"),
SUMMER("夏天","炎热"),
AUTUMN("秋天","凉爽"),
WINNER("冬天","寒冷");
// 季节名称
private String seasonsName;
// 季节描述
private String seasonDesc;
/**
* 构造方法,初始化季节名称和描述。
* seasonsName 季节的名称。
* seasonDesc 季节的描述。
*/
Seasons(String seasonsName,String seasonDesc){
this.seasonsName=seasonsName;
this.seasonDesc=seasonDesc;
}
/**
* 获取季节名称。
* @return 返回季节名称。
*/
public String getSeasonsName(){return seasonsName;}
/**
* 设置季节名称。
*
* 要设置的季节名称。
*/
public void setSeasonsName(String seasonsName){ this.seasonsName =seasonsName;}
/**
* 获取季节描述。
*
* @return 返回季节描述。
*/
public String getSeasonDesc(){return seasonDesc;}
/**
* 设置季节描述。
*
* @param seasonDesc 要设置的季节描述。
*/
public void setSeasonDesc(String seasonDesc) {
this.seasonDesc = seasonDesc;
}
}
枚举自带的方法
Seasons[] seasons=Seasons.values();//
- values() 返回枚举类中所有的值。
访问私有化成员变量
Seasons s = Seasons.WINNER; System.out.println(s.getSeasonsName()+","+s.getSeasonDesc());