问题:什么是面向对象编程?面向过程与面向对象有什么区别?
面向过程与面向对象都是一种思想,后者是相对于前者而言的;前者强调的是功能行为,而后者将功能封装进对象,强调的是具备了功能的对象;面向对象更加强调运用人类日常思维逻辑中采用的思想方法与原则,如抽象、分类、继承、聚合、多态等。 // 针对“人把大象装入冰箱”事件,分析面向对象与面向过程 面向过程: 人打开冰箱 -> 人将大象装入冰箱 -> 人关闭冰箱 面向对象: 三类:人类、大象类、冰箱类 人类 { 打开(冰箱) { 冰箱.开门(); } 装入(大象, 冰箱) { 大象.进入(冰箱); } 关闭(冰箱) { 冰箱.关门(); } } 大象类 { 进入(冰箱) { // 具体实现 } } 冰箱类 { 开门() { // 具体实现 } 关门() { // 具体实现 } }面向对象的思想概述:
完成需求时,需要先看所要完成的功能对应的类的对象是否存在;若存在,则通过对象直接调用对应的类中的属性和方法,完成需求即可;若不存在,则需要创建类的对象,甚至说类都不存在,就需要设计类。面向对象的三大主线:
Java类及类的成员:属性、方法、构造器、代码块和内部类;面向对象的三大特征:封装性(Encapsulation)、继承性(Inheritance)、多态性(Polymorphism);其他关键字:this、super、package、import、static、final、abstract、interface等。类(class)和对象(object)是面向对象的核心概念,类是对一类事物的描述,而对象是实际存在的该类事物的个体。面向对象程序设计的重点是类的设计,而定义类其实是定义类中的成员,即成员变量和成员方法。
Java代码是由诸多个不同功能的类构成的,而类主要是由属性、方法、构造器、代码块和内部类组成,属性对应类中的成员变量,行为对应类中的成员方法。 其中,Java类的语法格式如下:
// 修饰符public表示类可以被任意访问、类的正文要用"{}"括起来 修饰符 class 类名 { 属性声明; 方法声明; }附类与类之间的关系:关联关系、继承关系、聚合关系(聚集和组合)三种。
面向对象思想的落地法则:
设计类,并设计类的成员(属性、方法、构造器等);通过类,创建类的对象,即类的实例化;通过“对象名.对象成员”的方式来调用其成员,以完成相应的功能。. 类的实例化:
类名 对象名 = new 类名(); // 即new+构造器内存的基本结构:
栈空间(stack):存放局部变量、对象的引用名、数组的引用名;堆空间(heap):new出来的东西,即数组的实体、对象的实体,含成员变量;方法区:存放包名、类名和方法的定义,常量池(如字符串常量池);静态域:存放静态变量。. 类对象的内存解析: 例如,Animal animal = new Animal();语句的执行过程为:
在栈空间中,声明animal变量,用于存放对象的引用;在堆空间中,为所创建的对象开辟空间,利用构造器对其成员进行初始化;将所创建的对象在堆中开辟的空间首地址传递给栈空间中的引用变量animal;由此,即建立起栈空间中animal变量与堆空间中所创建对象之间的关系。属性声明的语法格式:
修饰符 数据类型 属性名 = 初值; // 权限修饰符有public、protected、private和缺省四种成员变量与局部变量:
对比点成员变量局部变量基本定义在方法体外、类体内声明的变量在方法体内声明的变量具体分类类变量(以static修饰)、实例变量形参、方法局部变量、代码块局部变量声明形式修饰符 数据类型 属性名 = 初值;数据类型 属性名 = 初值; //没有修饰符,默认与所在方法修饰符相同作用区域有,范围较大有,范围较小初始化值不同数据类型有不同默认初始化值无默认初始化值,必须显式赋值内存存储存放在堆空间中存放在栈空间中方法声明的语法格式:
// 返回值类型:return语句传递返回值,若没有返回值则用void 权限修饰符 返回值类型 方法名(参数列表) { 方法体语句; }注意:方法即提供某种功能的实现,方法内可以调用本类的其他属性或方法,但是不能在方法内再定义方法。
定义可变个数的形参的方法:
/** * 可变个数形参定义格式:“数据类型 ... 形参名” 或 “数据类型[] 形参名”,两者是一致的; * 可变个数的形参的方法与同名的方法之间构成重载; * 在一个方法中,最多可声明一个可变个数的形参,且其一定要声明在方法形参的最后。 */ //采用数组形参来定义方法 public static void test(int a ,String[] books); //以可变个数形参来定义方法 public static void test(int a ,String … books);Java中方法的参数传递方式为值传递机制,即
若形参是基本数据类型的,则将实参的值传递给形参的基本数据类型的变量;若形参是引用数据类型的,则将实参的值(对应堆空间中对象实体的首地址)传递给形参的引用数据类型的变量。注意:方法中的变量均为局部变量,存放在内存的栈空间中。理解值传递的基本原理:
// 方式一:交换两个变量的值 int i = 10; // 栈空间中,变量i所指向的内存地址存放的数据为10 int j = 5; int temp = i; // 基本数据类型:值传递,即传递的是10 i = j; j = temp; // 方式二:交换两个变量的值,该实现是错误的 public void swap(int i,int j){ // main方法中i=10,j=5 int temp = i; i = j; j = temp; // main方法将变量值传递给形参,形参值互换后不影响实参值 } // 方式三:交换两个变量的值 public void swap(DataSwap d){ // 传入的是对象的引用,即实参对象在堆空间的首地址 int temp = d.i; d.i = d.j; d.j = temp; }子类继承父类后,若父类的方法对子类不适用,即可对父类的方法进行重写;其与方法重载的不同之处在于:
对比点方法的重写方法的重载类在子类中重写父类的方法在同一个类中返回值类型与父类方法的返回值类型相同与被重载方法的返回值类型相同或不同均可方法名与父类方法的名称相同与被重载方法的名称相同参数列表与父类方法的参数列表相同与被重载方法的参数列表不同构造器不存在构造器的重写构造器是可以重载的构造器的声明格式:
// 构造器的作用:创建对象,并为所创建对象进行初始化; 权限修饰符 类名(参数列表) { 初始化语句; // 可为属性进行初始化操作 }注意事项:
若设计类时不显式声明类的构造器,程序则会提供一个默认的无参的构造器;若设计类时显式声明了类的构造器,程序则不会提供一个默认的无参构造器;每一个Java类都至少有一个构造器,其不能被static、final、synchronized、abstract、native等关键字修饰,且多个构造器之间构成重载。类对象属性赋值的先后顺序: 默认初始化 > 显式初始化、代码块初始化 > 构造器中赋值 > 通过“对象.方法”的方式为对象的属性赋值。
初始化块(代码块)的作用主要是为Java对象进行初始化,其与显示初始化同级别按代码的先后顺序执行。 初始化块的声明格式:
class className { 修饰符 { // 若有修饰符只能为static 初始化语句; // 为类属性进行初始化操作 } // 其他属性或方法声明 }静态代码块与非静态代码块:
对比点静态代码块非静态代码块修饰符static无输出语句其中可以有输出语句其中可以有输出语句初始化对象类的属性和声明,除非静态的属性外类的属性和声明可调用对象不可调用非静态的属性和方法可调用静态的属性和方法执行顺序多个静态代码块从上到下执行,且先于非静态代码块多个非静态代码块从上到下执行执行次数只执行一次每次创建对象时即执行一次,且先与构造器执行实例:继承类中静态代码块、非静态代码块和构造器的执行先后顺序。
在Java中,允许一个类的定义于另一个类内部,前者称为内部类,后者称为外部类。内部类分为成员内部类和局部内部类,成员内部类声明在类内方法外,而局部内部类声明在类内方法里。
作为外部类的成员:
可以声明为final、abstract;和外部类不同,内部类可以使用四种权限修饰符进行修饰;可以声明为static的,但此时不可使用外层类的非static的成员。作为类:
可以声明为abstract类,故可被其它的内部类所继承;注意:只有在外部类或static内部类中才可以声明static成员。 package com.whut.qiaobc.practice; public class Animal { private int num = 66; // 非静态内部类 public class Dog { private int num = 18; public void display(int num) { System.out.println(num); // 2.1 局部变量num System.out.println(this.num); // 2.2 内部类对象属性num System.out.println(Animal.this.num); // 2.3 外部类对象属性num } } // 静态内部类 public static class Bird { public int num = 33; } public static void main(String[] args) { // 1.1 创建非静态内部类对象 Animal animal = new Animal(); Animal.Dog dog = animal.new Dog(); dog.display(22); // 1.2 创建静态内部类对象 Animal.Bird bird = new Animal.Bird(); System.out.println(bird.num); } }局部内部类是指在类的方法中定义的内部类,其作用范围是该方法体;需要注意的是,局部内部类是方法的一部分,而非外部类的成员,故外部类不能访问该内部类,但该内部类可以访问当前代码块的常量以及此外部类的所有成员。
public Comparable getComparable() { // 局部内部类 class MyComparable implements Comparable { public int compareTo(java.lang.Object obj) { return 0; } } // 返回类的对象 return new MyComparable(); }匿名内部类不能定义任何静态成员、方法和类,只能创建匿名内部类的一个实例。一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
public Comparable getComparable() { // 匿名内部类 return new Comparable { public int compareTo(java.lang.Object obj) { return 0; } }; }