目录
引言
本文仅供个人学习侧重概念,有参考,有错误欢迎指正,感谢!
程序设计思想
面向过程
面向对象(Process-Oriented Programming ,POP)这种模式编写的程序以一系列的线性步骤(代码)为特征,可被理解为作用于数据的代码。典型语言为C语言,以函数为组织单位,重点关注的是操作数据的过程。
面向对象
面向对象编程(Object-Oriented Programming ,OOP)核心思想是将程序中的实体、数据和功能抽象为单独的对象,并在这些对象之间建立联系。典型语言为Java、C#、C++、Python、PHP等,以类为组织单位,重点在于类的设计。
举个例子:人把大象装进冰箱
面向过程:人打开冰箱 -> 人把大象装进冰箱 -> 人关上冰箱
面向对象:
分为三个对象:人、大象、冰箱
人:打开冰箱{冰箱.打开}、操作大象{大象.进入冰箱}、关闭冰箱{冰箱.关闭}
大象:进入冰箱
冰箱:打开、关闭
实现:人.打开冰箱 -> 人.操作大象 -> 人.关闭冰箱
两者关系
面向对象和面向过程是相辅相成的,面向对象离不开面向过程
类和对象
对象:代表了现实世界中的一个实体或抽象概念,并将其属性和行为抽象为程序中的数据结构和函数。
类:为属于该类的所有对象提供统一的抽象描述
例如:抽象概念的人是类,实实在在的某个人是对象
面向对象的基本特征
- 封装
它将对象的实现细节隐藏起来,只向外暴露对象的公共接口。可以使得对象的内部实现细节不被外部代码所依赖,从而提高代码的灵活性和可重用性。同时,还可以隐藏对象的内部状态,从而避免因为外部代码对对象状态的不正确使用导致的问题。
- 继承
允许一个类继承另一个类的特性,从而减少代码的重复编写。当一个类继承另一个类时,它会自动获得父类的所有属性和行为,并且可以在其上面扩展新的特性或覆盖父类中的某些特性。
- 多态
指的是同一消息可以被不同的对象响应,产生不同的行为。提高代码的灵活性和可重用性,减少程序的代码冗余。
多态分为两类:
运行时多态:也称为动态多态,是通过继承和接口实现的。在运行时,程序根据对象的实际类型来决定其行为,因此可以实现不同类型对象的不同行为。
编译时多态:也称为静态多态,是通过重载实现的。在编译时,程序根据函数的参数类型来决定调用哪个函数,因此可以实现不同参数类型对象的不同行为。
成员变量和局部变量
类中的变量称为成员变量,类中方法体内定义的变量和方法的参数称为局部变量。
两者共同之处:
①变量类型都可以是Java中任何一种数据类型;
②变量名字都必须符合标识符规定。
两者不同之处:
①成员变量在整个类中都有效,局部变量只在定义它的方法体内有效;
②若成员变量与局部变量名称相同,则在方法里成员变量将不生效,若想在该方法内使用成员变量则必须添加关键词this,即 this.成员变量;
③成员变量在对象被创建时分配在堆内存中的,随着对象的生命周期而存在。局部变量在方法执行时存在于栈内存中的,当方法调用结束时这些局部变量就会被销毁。
④成员变量都有默认初始化值,局部变量没有故使用之前必须赋值。
成员变量声明关键词
static :静态变量、相当于实例变量,该变量除了能够通过对象进行访问之外也能直接通过类名进行访问。
final:常量,该变量被初始化后,后续不能再修改。
transient:该将对象序列化为字节流时,该成员变量不参与序列化的过程或者对象存储到分布式缓存中时避免某些成员变量被缓存。(序列化:在java中对象可以序列哈为字节流,以便在网络上传输或者保存到文件中,但是有些成员变量可能不应该被序列化,比如密码、临时变量等,这些可以用transient关键字来标记这些成员变量)
volatile:用于并发编程的共享,可看这篇文章写得很细 Java volatile关键字最全总结
局部变量
对于方法内声明的局部变量来说:
如果该值的类型是基本数据类型,则传递的是变量保存的数据值;
如果该值的类型是引用数据类型,则传递的是变量保存的地址值。
也就是说,基本数据类型变量在栈中存储的是值,引用数据类型变量存储的是地址。
成员方法
格式:
public/protected/缺省/private [static] [final/abstract] [native] [synchronized] 返回类型 方法名(形参类型 形参名) [throws 异常类型]{ ... }
注:[]里的部分不是必须的,缺省即不写任何关键字
限定词:
static:类方法,可通过类名直接调用
abstract:抽象方法,没有方法体
final:方法不能被重写
native:调用非java代码的接口,即实体实现的语言不是Java
synchronized:控制多个并发线程的访问,可以防止多个线程同时访问这个对象的synchronized方法
可变个数形参的方法
在调用方法时可能会出现确定了形参类型,但是不确定参数的个数数量的情况,此时可以使用...将参数个数设置为可变的。
格式:(参数类型 ... 参数名)
注:
①若出现了与 可变个数形参方法 同名同形参类型 的 指定个数方法 时,调用该方法时会优先查找指定个数方法,若都不符合再找可变个数形参方法。
②若与其他指定个数形参进行结合,要求可变个数形参写在最右
③每个方法中最多只有一个可变个数形参
例如:
public class Test{
public static void main(String[] args){
Test test = new Test();
test.print(); //11
test.print(2,3); //22
test.print(1); //33
test.print(2,3,4);//11
test.print(new int[]{5,6,7});//11
test.print("qq");//44
}
public void print(int ... counts){
System.out.println("11");
}
public void print(int arg1, int arg2){
System.out.println("22");
}
public void print(int arg1){
System.out.println("33");
}
//可变个数形参写最右
public void print(String arg1,int ... counts){
System.out.println("44");
}
}
重载
在同一个类中,允许存在一个以上的同名方法,只要它们的形参列表(形参的个数或类型)不同即可。
特例:可变个数形参的方法 与 形参类型和可变个数形参的类型相同的 的方法不构成重载,属于相同方法,不能在同一个类中定义。
例如:
public class Test{
public void print(int ... counts){
...
}
//报错,'print(int[])' is already defined in 'Test'
public void print(int[] arr){
...
}
}
递归方法
方法自己调用自己的现象称为递归。
分类:
直接递归(方法自己调用自己)
间接递归(即方法A调用方法B,方法B调用方法C,方法C调用方法A)
注:递归一定要有停止递归的条件,否则会变成无穷递归停不下来,导致“栈内存溢出”(StackOverflowError)。要求高性能的情况下尽量避免使用递归。
例如:快速排序、斐波那契数列
//斐波那契数列(下一个数为前两个数的和)
public class Test{
public static void main(String[] args) {
for (int i = 1; i <= 6; i++) {
System.out.print(add(i) + " ");//1 1 2 3 5 8
}
}
private static int add(int n) {
if (n == 1 || n==2){
return 1;
}else {
return add(n-1)+add(n-2);
}
}
}
对象数组
数组的元素类型可以是基本数据类型也可也是引用数据类型,当元素是引用类型中的类是,称为对象数组。
下面是创建对象数组并对每个对象元素进行实例化的错误做法(第一种)以及正确做法(第二种)。new Student()
创建了一个 Student
类的新实例,会在内存的堆区分配空间来存储这个新对象的成员变量,错误方法中只创建了一个新对象,并将数组中所有元素都指向了这个对象
方法的值传递机制
值传递机制。
形参:在定义方法时,方法名后面括号()中声明的变量称为形式参数,简称形参。
实参:在调用方法时,方法名后面括号()中的使用的值/变量/表达式称为实际参数,简称实参。规则:实参给形参赋值的过程
如果形参是基本数据类型的变量,则将实参保存的数据值赋给形参。
如果形参是引用数据类型的变量,则将实参保存的地址值赋给形参。
构造器
实际上每一个类中都有一个构造器,若不写,系统会默认提供一个空参的构造器。
作用:
搭配new关键词,创建类的对象;
在创建对象的同时可以给对象的相关属性赋值
格式:
权限修饰符 类名(形参列表){
...
}
例如:
public class Test{
public static void main(String[] args){
Person p = new Person(10);
}
}
public class Person{
private int age;
//构造器
public Person(int age){
this.age = age;
}
}