02-1面向对象编程
2021/12/22 1:19:57
本文主要是介绍02-1面向对象编程,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
1面向过程与面向对象思想
二者都是一种思想,面向对象是相对于面向过程而言的。
面向过程(POP),强调的是功能行为,以函数为最小单位,考虑怎么做。
面向对象(OOP),将功能封装进对象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。
面向对象更加强调运用人类在日常的思维逻辑中采用的思想方法与原则,如抽象、分类、继承、聚合、多态等
面向对象思想比面向过程思想更高级
程序员从面向过程的执行者转化成了面向对象的指挥者
面向过程思想:算法+数据结构
面向对象思想:数据结构+算法
看一个实例来理解面向过程和面向对象的区别,
人开车上班
package com.nie.classandobject; /** * @author nzy * @create 2021-12-16 17:18 */ public class Class1 { //面向过程和面向对象的区别 //举例:开车上班 } //面向过程 class POPTest{ //启动车 public void startCar(){ System.out.println("小王启动车"); } //开车中 public void driverCaring(){ System.out.println("小王开车中"); } //到目的 停车锁车 public void stopCar(){ System.out.println("小王停车中"); } } //面向对象编程 class Car{ public void startCar(){ System.out.println("启动车"); } //开车中 public void driverCaring(){ System.out.println("开车中"); } //到目的 停车锁车 public void stopCar(){ System.out.println("停车中"); } } class Person{ //不关心Car内部方法的实现, public void driverCar(Car car){ car.startCar(); car.driverCaring(); car.stopCar(); } }
面向对象分析方法分析问题的思路和步骤:
- 根据问题需要,选择问题所针对的现实世界中的实体。
- 从实体中寻找解决问题相关的属性和功能,这些属性和功能就形成了概念世界中的类。
- 把抽象的实体用计算机语言进行描述,形成计算机世界中类的定义。即借助某种程序语言,把类构造成计算机能够识别和处理的数据结构。
- 将类实例化成计算机世界中的对象。对象是计算机世界中解决问题的最终工具
面向对象程序设计的重点是类的设计
类的设计,就是类的成员的设计
面向对象程序设计(简称OOP)是当今主流的程序设计范型,它已经取代了20世纪70年代的“结构化”过程化程序设计开发技术。Java是完全面向对象的,必须熟悉OOP才能够编写Java程序。
面向对象的程序是由对象组成的,每个对象包含对用户公开的特定功能部分和隐藏的实现部分。程序中的很多对象来自标准库,还有一些是自定义的。究竟是自己构造对象,还是从外界购买对象完全取决于开发项目的预算和时间。但是,从根本上说,只要对象能够满足要求,就不必关心其功能的具体实现过程。在OOP中,不必关心对象的具体实现,只要能够满足用户的需求即可。
2类的组成成员(属性,方法,构造器,代码块,内部类)
客观存在的事物皆为对象 ,所以我们也常常说万物皆对象。
类(Class)和对象(Object)是面向对象的核心概念
面向对象程序设计的重点是类的设计,类的设计就是设计类的成员
类
- 类的理解
类是对现实生活中一类具有共同属性和行为的事物的抽象
类是对象的数据类型,类是具有相同属性和行为的一组对象的集合
简单理解:类就是对现实事物的一种描述 - 类的组成
属性:指事物的特征,例如:手机事物(品牌,价格,尺寸)对应类中的成员变量
行为:指事物能执行的操作,例如:手机事物(打电话,发短信)对应类中的成员方法 - 类和对象的关系
类:类是对现实生活中一类具有共同属性和行为的事物的抽象
对象:是能够看得到摸的着的真实存在的实体个体,也称为实例
简单理解:类是对事物的一种描述,对象则为具体存在的事物
类的语法格式
修饰符 class 类名 { 属性声明; 方法声明; }
对象的创建(实例化)
创建对象语法: 类名 对象名 = new 类名();
使用“对象名.对象成员”的方式访问对象成员(包括属性和方法)
如果创建了一个类的多个对象,对于类中定义的属性,每个对象都拥有各自的一套副本,且互不干扰。
类访问机制
- 在一个类中的访问机制:类中的方法可以直接访问类中的成员变量。 (例外:static方法访问非static,编译不通过。)
- 在不同类中的访问机制:先创建要访问类的对象,再用对象访问类中定义的成员
2.1属性
属性:类中的成员变量
语法格式:
修饰符 数据类型 属性名 = 初始化值 ;
- 常用的权限修饰符有:private、缺省、protected、public
- 其他修饰符:static、final
// 属性 : 姓名, 年龄 private String name; int age;
可以不赋值,默认的值是
元素类型 | 元素默认初始值 |
byte | 0 |
short | 0 |
int | 0 |
long | 0L |
float | 0.0F |
double | 0.0 |
char | 0 或写为:’\u0000’(表现为空) |
boolean | false |
引用类型 | null |
属性分类:成员变量和局部变量
- 在方法体外,类体内声明的变量称为成员变量。
- 在方法体内部声明的变量称为局部变量。
成员变量 | 局部变量 | |
声明的位置 | 直接声明在类中 | 方法形参或内部、代码块内、构造器内等 |
修饰符 | private、public、static、final等 | 不能用权限修饰符修饰,可以用final修饰 |
初始化值 | 有默认初始化值 | 没有默认初始化值,必须显式赋值,方可使用 |
内存加载位置 | 堆空间 或 静态域内 | 栈空间 |
在虚拟机中:非static存在于堆中,static存在于常量池中
2.2方法
方法(函数):描述类具备的某种行为,用来完成某个功能操作,
将功能封装为方法的目的是,可以实现代码重用,简化代码
声明格式
修饰符 返回值类型 方法名(参数类型 形参1, 参数类型 形参2, ….){ 方法体程序代码 return 返回值; }
修饰符:public,缺省,private,protected等
返回值类型:没有返回值:void。有返回值,声明出返回值的类型。与方法体中“return返回值”搭配使用
方法名:属于标识符,命名时遵循标识符命名规则和规范,“见名知意”
形参列表:可以包含零个,一个或多个参数。多个参数时,中间用“,”隔开
返回值:方法在执行完毕后返还给调用它的程序的数据
方法只有被调用时才会执行
形参:方法传递的参数
实参:方法调用时实际传给形参的参数值
// 行为 : 学习 public void study(String language){//language 形参 System.out.println("学习"+language); int num1 = 3;//局部变量 }
方法参数的值传递机制:实际参数值的副本(复制品)传入方法内,而本身参数不受影响,本身参数和副本都引用同一个对象,所以实参不是按引用调用的。
形参是基本数据类型:将实参基本数据类型变量的数据值传给形参
形参是引用数据类型:将实参引用数据类型变量的地址值传递给形参
方法可以修改引用数据的值,而不能修改基本数据的值(方法进入栈内存)
方法重载:
概念:在同一个类中,允许存在一个以上的同名方法,只要他们的参数个数或者参数类型不同
特点:与返回值类型无关,只看参数列表,且参数列表必须不同。(参数个数或者参数类型)调用时根据方法参数列表不同来区分
方法重写(Override):
定义:在子类中可以根据需要对从父类中继承来的方法进行改造,也称为方法的重置、覆盖。在程序执行时,子类的方法将覆盖父类的方法。
- 子类重写的方法必须和父类被重写的方法具有相同的方法名称、参数列表
- 子类重写的方法的返回值类型不能大于父类被重写的方法的返回值类型
- 子类重写的方法使用的访问权限不能小于父类被重写的方法的访问权限
- 子类不能重写父类中声明为private权限的方法
- 子类方法抛出的异常不能大于父类被重写方法的异常
子类与父类中同名同参数的方法必须同时声明为非static的(即为重写),或者同时声明为static的(不是重写)。因为static方法是属于类的,子类无法覆盖父类的方法。
可变形参的方法:
jdk5中提供了可变形参机制,调用方法时可以传递多个参数
1. 声明格式:方法名(参数的类型名 ...参数名)
2. 可变参数:方法参数部分指定类型的参数个数是可变多个:0个,1个或多个
3. 可变个数形参的方法与同名的方法之间,彼此构成重载
4. 可变参数方法的使用与方法参数部分使用数组是一致的
5. 方法的参数部分有可变形参,需要放在形参声明的最后
6. 在一个方法的形参位置,最多只能声明一个可变个数形参
public class MethodArgsTest { public static void main(String[] args) { MethodArgsTest test = new MethodArgsTest(); test.show(12); test.show("hello"); test.show("hello","world"); test.show(); test.show(new String[]{"AA","BB","CC"}); } public void show(int i){ } public void show(String s){ System.out.println("show(String)"); } public void show(String ... strs){ System.out.println("show(String ... strs)"); for(int i = 0;i < strs.length;i++){ System.out.println(strs[i]); } } //不能与上一个方法同时存在 // public void show(String[] strs){ // // } //The variable argument type String of the method //show must be the last parameter // public void show(String ...strs,int i){ // // } }
源码中经常使用
递归方法
递归方法:一个方法体内调用它自身。
方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制。
递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环。
// 例:计算1-n之间所有自然数的和 public int getSum(int n) { if (n == 1) { return 1; } else { return n + getSum(n - 1); } }
2.3构造器
java中使用构造器(构造函数)来创建对象,构造器是一种特殊的方法,用来初始化对象
编写规范:
- 它具有与类相同的名称
- 它不声明返回值类型。(与声明为void不同)
- 不能被static、final、synchronized、abstract、native修饰,不能有return语句返回值
- 构造器配合new运算符来创建对象
作用:创建对象;给对象进行初始化
语法格式:
修饰符 类名 (参数列表) {
初始化语句;
}
Person p;//此时并没有创建对象,必须new //创建一个Date对象 Date date = new Date(); //Date的构造方法 public Date() { this(System.currentTimeMillis()); }
一个类没有编写构造器时,默认会提供一个无参的构造器,并将所有的实例字段设置为默认值
根据参数不同,构造器可以分为如下两类:
- 隐式无参构造器(系统默认提供)
- 显式定义一个或多个构造器(无参、有参)
注 意:
- Java语言中,每个类都至少有一个构造器
- 默认构造器的修饰符与所属类的修饰符一致
- 一旦显式定义了构造器,则系统不再提供默认构造器
- 一个类可以创建多个重载的构造器
- 父类的构造器不可被子类继承
调用父类的构造器
子类中所有的构造器默认都会访问父类中空参数的构造器
当父类中没有空参数的构造器时,子类的构造器必须通过this(参数列表)或者super(参数列表)语句指定调用本类或者父类中相应的构造器。同时,只能”二选一”,且必须放在构造器的首行
如果子类构造器中既未显式调用父类或本类的构造器,且父类中又没有无参的构造器,则编译出错
2.4代码块
初始化块,在类中声明,只要构造类的对象,这个代码块就会执行,
作用:用来初始化类、对象
静态代码块和非静态代码块
静态代码块:用static 修饰的代码块
- 可以有输出语句。
- 可以对类的属性、类的声明进行初始化操作。
- 不可以对非静态的属性初始化。即:不可以调用非静态的属性和方法。
- 若有多个静态的代码块,那么按照从上到下的顺序依次执行。
- 静态代码块的执行要先于非静态代码块。
- 静态代码块随着类的加载而加载,且只执行一次。
非静态代码块:没有static修饰的代码块
- 可以有输出语句。
- 可以对类的属性、类的声明进行初始化操作。
- 除了调用非静态的结构外,还可以调用静态的变量或方法。
- 若有多个非静态的代码块,那么按照从上到下的顺序依次执行。
- 每次创建对象的时候,都会执行一次。且先于构造器执行。
代码块不常见,直接将初始化代码放在构造器中执行会更好
2.5内部类
当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构最好使用内部类。
在Java中,允许一个类的定义位于另一个类的内部,前者称为内部类,后者称为外部类。
Inner class一般用在定义它的类或语句块之内,在外部引用它时必须给出完整的名称。
Inner class的名字不能与包含它的外部类类名相同;
分类: 成员内部类(static成员内部类和非static成员内部类)局部内部类(不谈修饰符)、匿名内部类
和外部类不同,Inner class还可以声明为private或protected
可以调用外部类的结构
Inner class 可以声明为static的,但此时就不能再使用外层类的非static的成员变量;(懒汉式单例模式的一种写法)
成员内部类作为类的角色:
- 可以在内部定义属性、方法、构造器等结构
- 可以声明为abstract类 ,因此可以被其它的内部类继承
- 可以声明为final的
- 编译以后生成OuterClass$InnerClass.class字节码文件(也适用于局部内部类)
注意:
1. 非static的成员内部类中的成员不能声明为static的,只有在外部类或static的成员内部类中才可声明static成员。
2. 外部类访问成员内部类的成员,需要“内部类.成员”或“内部类对象.成员”的方式
3. 成员内部类可以直接使用外部类的所有成员,包括私有的数据
4. 当想要在外部类的静态成员部分使用内部类时,可以考虑内部类声明为静态的
public class InnerClassTest { public static void main(String[] args) { //创建Dog实例(静态的成员内部类): Person.Dog dog = new Person.Dog(); dog.show(); //创建Bird实例(非静态的成员内部类): // Person.Bird bird = new Person.Bird();//错误的 Person p = new Person(); Person.Bird bird = p.new Bird(); bird.sing(); System.out.println(); bird.display("黄鹂"); } } class Person{ String name = "小明"; int age; public void eat(){ System.out.println("人:吃饭"); } //静态成员内部类 static class Dog{ String name; int age; public void show(){ System.out.println("卡拉是条狗"); // eat(); } } //非静态成员内部类 class Bird{ String name = "杜鹃"; public Bird(){ } public void sing(){ System.out.println("我是一只小小鸟"); Person.this.eat();//调用外部类的非静态属性 eat(); System.out.println(age); } public void display(String name){ System.out.println(name);//方法的形参 System.out.println(this.name);//内部类的属性 System.out.println(Person.this.name);//外部类的属性 } } public void method(){ //局部内部类 不常用 class AA{ } } { //局部内部类 class BB{ } } public Person(){ //局部内部类 class CC{ } } }
3权限修饰符
Java权限修饰符public、protected、(缺省)、private置于类的成员定义前,用来限定对象对该类成员的访问权限。
修饰符 | 类内部 | 同一个包 | 不同包的子类 | 同一个工程 |
private | Yes | |||
(缺省) | Yes | Yes | ||
protected | Yes | Yes | Yes | |
public | Yes | Yes | Yes | Yes |
对于class的权限修饰只可以用public和default(缺省)。
- public类可以在任意地方被访问。
- default类只可以被同一个包内部的类访问。
4匿名对象和匿名类
匿名:没有名字
匿名创建的对象只使用一次
可以创建匿名对象后调用该对象的方法
public class PersonTest { public void save(Person person){ //业务逻辑 } public static void main(String[] args) { PersonTest test1 = new PersonTest(); test1.save(new Person());//new Person() 就是匿名对象。匿名没有名字 new PersonTest().save(new Person()); //创建了一个匿名Runnable子类的对象 new Thread(new Runnable() { @Override public void run() { } }); } }
这篇关于02-1面向对象编程的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-09-19JAVA 企业级项目入门:从零开始的实战指南
- 2024-09-19Java 企业级项目入门:从零基础到实战的进阶之路
- 2024-09-19Java 企业级项目入门:从零开始的实战指南
- 2024-09-18Java OA系统入门:从基础到实践
- 2024-09-18Java OA系统入门:从零开始的简单教程
- 2024-09-18JAVA OA系统入门:从零开始的实战指南
- 2024-09-18Java Web项目入门:快速搭建你的第一个Web应用
- 2024-09-18JAVA web项目入门:从零基础到实战的小白指南
- 2024-09-18Java Web项目入门:从零开始的轻量级教程
- 2024-09-18Java Web项目入门:快速搭建与基础实践