三、面向对象编程
(一)
1.面向对象与面向过程
定义:面向对象是相对于面向过程而言的。面向过程,强调的是功能行为。面向对象,将功能封装进对象,强调具备了功能的对象
一.面向对象的落地法则一:
1.设计类,并设计类的成员(成员变量&成员方法)
2.通过类,来创建类的对象(也称作类的实例化)
3.通过“对象.属性”或“对象.方法”来调用,完成相应功能。
类的实例化在内存的结构
二.创建多个对象,彼此各自拥有一套类的属性,当对其中一个对象的属性进行修改时,不会影响到其他对象的属性值。
三.类的属性(成员变量)
成员变量 vs 局部变量
相同点:1.遵循变量声明的格式: 数据类型 变量名 = 初始化值
2.都有作用域
不同点:1.声明的位置的不同:成员变量:声明在类里,方法外
局部变量:声明在方法方法内,方法的形参部分,代码块内
2.成员变量的修饰符有四个:public private protected 缺省
局部变量没有修饰符,与所在的方法修饰符相同。
3.初始化值:一定有初始化值
成员变量:如果在声明的时候,不显示赋值,那么不同数据类型会有不同的默认初始化值。
byte short int long ==>0
float double ==>0.0
char ==>空格
boolean==>false
引用类型变量 ==>null
局部变量:一定要显式的赋值。(局部变量没有默认初始化值)
4.二者在内存中存放的位置不同:成员变量存在于堆空间中;局部变量存放在栈空间中
四.类的方法
1)格式:权限修饰符 返回值类型(void:无返回值/具体的返回值) 方法名(形参){}
2)关于返回值类型:有返回值的方法:在方法的最后一定有return + 返回值类型对应的变量
2.类与类之间的关系
1.关联关系:关联体现的是两个类之间语义级别的一种强依赖关系,属于强耦合。这种关系比依赖强、不存在依赖关系的偶然性、关联关系也不是临时性的,一般是长期性的,而且双方的关系一般是平等的。关联可以是单向、双向的。体现在代码上是,类A中有类B中的成员变量。
class abstract class AbstractGun{ //抽象射击方法 public void shoot(); }
class Rifle extends AbstractGun{
//设计射击方法实现 public void shoot(){ System.out.println("步枪射击");
}
}
class Soldier{
//定义士兵的枪支
private AbstractGun gun;
public void setGun(AbstractGun _gun){
this.gun=_gun;
}
public void killEnemy(abstractGun gun){
System.out.println("士兵开始杀人");
gun.shoot();
}
}
class client{
public static void main(String [] args){
Soldier solder=new Soldier();
solder.setGun(new Rifle());
solder.killEnemy();
}
}
//类client与类soldier是依赖关系,
//类soldier与类AbstractGun是一种关联关系。Soldier中有AbstractGun的类变量
//类Rifle与类AbstractGun是一种继承关系
2.继承关系(泛化关系)
3.聚合关系:聚合是关联关系的一种特例,体现在整体与部分到的关系,即has-a的关系。此时整体与部分之间是可分离的,他们可以具有各自的生命周期,部分可以属于多个整体对象,也可以为多个整体对象共享。比如计算机与CPU、公司与员工的关系等。表现在代码上与关联关系是一致的。
4.实现关系:实现指的是一个类实现interface接口的功能。从类指向实现的接口。
5.依赖关系:类A使用到类B,但这中使用关系是具有偶然性、临时性的,属于弱耦合。
在代码上体现在,类A中含有类B的局部变量
A中方法名(Class B){ }
6.组合关系:组合也是关联关系的一种特例,体现的是一种contains-a的关系,这种关系比耦合更强,也称为强聚合。它同样体现整体与部分间的关系,但此时整体与部分是不可分的,整体声明周期结束意味着部分生命周期结束。
3.面向对象思想的概述
类:对一类事物的面熟,是抽象的、概念上的定义
对象:实际存在的该类食物的每个个体,因而也称实例
4.属性:对应类中的成员变量
行为:对应类中成员方法
5.方法的重载overload
要求:1.求同一个类中
2.方法名必须相同
3.方法的参数列表不同(①参数的个数不同②参数的类型不同)
补充:方法的重载与方法的返回值类型没有关系。
参数个数相同,参数的类型相同,但顺序不同依然能构成重载。
public class Person {
private String name;
private int age;
public void eat(){
System.out.println("人吃饭");
}
public void eat(String name){
System.out.println(this.name + "吃饭");
}
public void eat(String name,int age){
System.out.println(this.name + this.age + "吃饭");
}
public void eat(int age,String name){
System.out.println(this.age + this.name + "吃饭");
}
}
6.匿名对象
匿名类对象:创建的类的对象是匿名的
1)当我们只需要一次调用类的对象时,我们就可以考虑使用匿名的方式创建类的对象
2)特点:创建的匿名类对象只能调用一次。
new XXX({});
public void test1(){
new Son(){
public void show() {
// TODO Auto-generated method stub
System.out.println("跳舞");
}
}.show();
}
}
class Son{
}
7.可变个数的形参的方法
可变个数的方法
1.格式:对于方法的形参:数据类型 ...形参名
2.可变个数的形参的方法与同名的方法之间构成重载
3.可变个数的形参再调用时,个数从0开始,到无穷个都可以
4.使用可变多个形参的方法的形参使用数组是一致的
5.若方法中存在可变个数的形参,那么一定要声明在方法参数的最后。
6.在一个方法中,最多声明一个可变的形参
@Test
public void test2(){
Person p =new Person();
p.eat(1);//吃
p.eat(2,"ss","sw");//qwe
p.eat(3,"awq","wd","aw","rt");//ss
}
class Person{
private String name;
private int age;
public void eat(int age){
System.out.println("吃");
}
public void eat(int age,String name1,String name2){
System.out.println("qwe");
}
public void eat(int age,String... name){
System.out.println("ss");
}
}
8.方法的参数传递
1.形参:方法声明时,方法小括号内参数
实参:调用方法时,实际传入的参数的值
2.规则:java中的参数传递机制:值传递机制
1)形参是基本数据类型的:将实参的值传递给形参的基本数据类型的变量
2)形参是引用数据类型的:将实参的引用数据类型变量的值(对应的堆空间的对象实体的首地址)传递给形参的引用类型变量
交换数组中指定位置的元素:交换arr数组中索引为i和j的两个元素
3.存储结构
9.类的成分之三:构造器
构造器(constructor 构造方法) contruction CCB ICBC oop
构造器的作用:①创建对象②给创建的对象的属性赋值
1.设计类时,若不显式声明类的构造器的话,程序会默认提供一个空参的构造器
2.一旦显式的定义类的构造器,那么默认的构造器就不再提供。
3.如何声明类的构造器,格式:权限修饰符 类名(形参){}
4.类的多个构造器之间构成重载
class Son{
private String name;
private int age;
private int banji;
public Son() {//构造器
super();
// TODO Auto-generated constructor stub
}
public Son(String name, int age, int banji) {
super();
this.name = name;
this.age = age;
this.banji = banji;
}
public Son(String name){
super();
this.name = name;
}
}
10.类对象的赋值
类对象的属性赋值的先后顺序:
1.静态属性初始化
2.静态代码块初始化
3.属性的默认初始化
4.属性的显式初始化
5.通过构造器给属性初始化
6.通过“对象.方法”的方式给属性赋值
@Test
public void test3(){
//5.通过构造器给属性初始化
Son s2 = new Son("小王",9,3);
Son s1 = new Son();
//6.通过“对象.方法”的方式给属性赋值
s1.setName("小明");
}
class Son{
//1.静态属性初始化
private static String name = "小赵";
//4.属性的显式初始化
private int age = 0 ;
//3.属性的默认初始化
private int banji;
//2.静态代码块初始化
static{
name = "小张";
}
public Son() {
super();
// TODO Auto-generated constructor stub
}
public Son(String name, int age, int banji) {
super();
this.name = name;
this.age = age;
this.banji = banji;
}
public Son(String name){
super();
this.name = name;
}
public static String getName() {
return name;
}
public static void setName(String name) {
Son.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getBanji() {
return banji;
}
public void setBanji(int banji) {
this.banji = banji;
}
}
(二)面向对象三大特征:
1.封装:
面向对象特性一:封装与隐藏
问题:当创建了类的对象以后,如果直接通过“对象.属性”的方式对相应的对象属性赋值的话,
可能会出现不满足实际情况的意外,我们考虑不让对象来直接作用属性,而是通过“对象.方法”
的形式,来控制对象对属性的访问。实际情况中,对属性的要求就可以通过方法来体现。
解决方法:(封装的思想)①将类的属性私有化。②提供公共的方法(setter&getter)来实现调用。
class Car{
private String name;
private int age;
private String carname;
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 String getCarname() {
return carname;
}
public void setCarname(String carname) {
this.carname = carname;
}
}
2.继承:
注:toString()方法显示在堆空间的地址值
<1>继承的定义
继承性
1.为什么要设计继承性?
2.通过"class A extends B"类实现类的继承
子类:A 父类(或基类SuperClass):B
3.子类继承父类以后,父类中声明的属性、方法,子类就可以获取到
明确:当父类中有私有的属性或方法时,子类同样可以获取得到,只是由于封装性的设计,使得子类不可以直接调用
子类除了通过继承,获取父类的结构之外,还可以定义自己的特有的成分
extends:子类是对父类功能的“扩展”,明确子类不是父类的子集。
4.java类的继承只支持单继承,一个类只能继承一个父类,一个父类可以有多个子类。
5.子父类只是相对的概念
class Person{
private String name;
private int age;
public void eat(){
System.out.println("吃");
}
}
class Man extends Person{
private String name;
private int age;
public void sleep(){
System.out.println("睡觉");
}
}
<2>方法的重写
方法的重写 -----(方法的重载)修饰符 返回值类型 方法名 (参数列表){}
1.前提:有子类继承父类
2.子类继承父类以后,若父类的方法对子类不使用,那么子类可以对父类的方法重写(override overwrite)
3.重写的规则: 1)要求子类方法的“返回值类型 方法名(参数列表)”与父类的方法一样
2)子类方法的修饰符不能小于父类方法的修饰符
3)若父类方法抛异常,那么子类方法抛的异常类型不能大于父类的
4)子父类的方法必须同为static或同为非static的。
class Person{
private String name;
private int age;
public void eat(){
System.out.println("吃");
}
}
class Man extends Person{
private String name;
private int age;
public void sleep(){
System.out.println("睡觉");
}
public void eat(){
System.out.println("男人吃饭");
}
}
<3>super
super:可以用来修饰属性、方法、构造器
1)当子类与父类中有同名的属性时,可以通过"super.此属性"显式的调用父类中声明的属性。
若想调用子类的同名的属性"this.属性"
2)当子类重写父类的方法以后,在子类中若想在显式的调用父类的被重写的方法,就需要使用"super.方法"
3)super修饰构造器,通过在子类中使用"super(形参列表)"来显式的调用父类中指定的构造器。
>在构造器内部,"super(形参列表)"必须声明在首行。
>在构造器内部,"this(形参列表)"或"super(形参列表)"只能出现一个。
>在构造器中,不显式的调用"this.(形参列表)"或"super(形参列表)"其中任何一个,默认调用的是父类空参的构造器。
建议:设计一个类时,尽量要提供一个空参的构造器。
public void test3(){
Man m1= new Man();
m1.sleep();
}
class Person{
String name;
int age;
public Person() {
super();
// TODO Auto-generated constructor stub
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public void eat(){
System.out.println("吃");
}
}
class Man extends Person{
String name;
int age;
public Man(String name){
super("xia",2);//调用person有参构造器
}
public Man(String name, int age) {
super();
super.name = name;//调用父类的属性
this.age = age;
}
public Man() {
super();
// TODO Auto-generated constructor stub
}
public void sleep(){
System.out.println("睡觉");
}
public void eat(){
System.out.println("男人吃饭");
}
public void read(){
super.eat();//调用父类的方法
}
}
<4>子类对象实例化的全过程
3.多态
多态性
1.多态性指的是什么?多态性,可以理解为一个事物的多种表型形态
1)方法的重载和重写2)子类对象的多态性
2.子类对象的多态性使用的前提:①要有类的继承②要有子类对父类方法的重写
3.程序运行分为编译状态和运行状态
对于多态性来说,编译时:"看左边",将此引用变量理解为父类的类型
运行时,"看右边",关注于真正对象的实体,子类的对象,那么执行的方法就是子类重写的。
子类对象的多态性:父类的引用指向子类对象
Person p1 = new Man();(向上转型)
虚拟方法调用:通过父类的引用指向子类的对象实体,当调用方法时,实际执行的时子类重写父类的方法
p1.eat();
p2.eat();
man对象的方法
子类特有的方法不能调用,调用的是重写的方法。
Person p2 = new Woman();
p2.eat();
p2.walk();
p2.shopping();//错的
Woman w = (woman)p2;(向下转型)
w.shopping();//对的
Woman w1 = (Woman)p1;
w1.shopping();//不会报错,运行时,转化异常。
instanceof判断引用数据类型
格式:对象a instanceof 类A
判断a是否是类A的一个实例,是的话,返回true,否则返回false
若a是A类的实例,那么a也一定是A类的父类的实例。
其他关键字:
1.this关键字
(1,可以用来修饰属性、方法、构造器
(2.this理解为当前对象或当前正在创建的对象,比如:this.name,this.show();
(3.可以在构造器中通过“this(形参)”的方式显示的调用本类中的其他重载的指定的构造器。
要求:1.在构造器的内部必须声明在首行
2.若一个类中有n个构造器,那么最多有n-1个构造器中使用了this();
2.javabean
JavaBean是一种Java语言写成的可重用组件。
标准:
1.类是公共的
2.有一个无参的公共的构造器
3.有属性,且有对应的get,set方法
+表示public类型 -表示private类型 #表示protected类型
3.package
package:声明源文件所在的包,写在程序的第一行
每“.”一次,表示一层文件目录
包名都要小写
4.import
import:
1)显式导入指定包下的类或接口
2)写在包的声明和源文件之间
3)如果需要引入多个类或接口,那么就并列写出
4)如果导入的类是java.lang包下的,如:system String Math就不需要显式的声明
5)理解.*的概念
6)如何处理同名类的导入。如:在util包和sql包下同时存在Date类
7)import static 表示导入指定类的static的属性或方法
8)导入java.lang.*只能导入lang包下的所有类或接口,不能导入lang的子包下的类或接口