面向过程,强调的是功能行为,以函数为最小单位
面向对象,将功能封装进对象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。面向对象更加强调运用人类在日常的思维逻辑中采用的思想方法与原则,如抽象,分类,继承,聚合,多态等。
- 封装(Encapsulation)
- 继承(Inheritance)
- 多态(Polymorphism)
面向对象的七大原则:
单一职责原则(Single Responsibility Principle)
每一个类应该专注于做一件事。
里氏替换原则(Liskov Substitution Principle)
超类存在的地方,子类是可以替换的。
依赖倒置原则(Dependence Inversion Principle)
实现尽量依赖抽象,不依赖具体实现。
接口隔离原则(Interface Segregation Principle)
应当为客户端提供尽可能小的单独的接口,而不是提供大的总的接口。
迪米特法则(Law Of Demeter)
又叫最少知识原则,一个软件实体应当尽可能少的与其他实体发生相互作用。
开闭原则(Open Close Principle)
面向扩展开放,面向修改关闭。
组合/聚合复用原则(Composite/Aggregate Reuse Principle CARP)
尽量使用合成/聚合达到复用,尽量少用继承。原则: -个类中有另一个类的对象。
关于组合和聚合参考:https://zhuanlan.zhihu.com/p/359672087`
类(Class)和对象(Object)是面向对象的核心概念。
类是对一类事物的描述,是抽象的、概念上的定义
对象是实际存在的该类事物的每个个体,因而也称为实例(instance)。
可以理解为:类=抽象概念的人;对象=实实在在的某个人
面向对象程序设计的重点是类的设计
类的设计,其实就是类的成员的设计
现实生物世界中的细胞又是由什么构成的呢?细胞核、细胞质、… 那么, Java中用类class来描述事物也
是如此。常见的类的成员有:
Field =属性=成员变量,Method = (成员)方法=函数
public class Persion1 {
String name;
int age;
/**
* sex: 1 表示是男性
* sex: 0 表示是女性
*/
int sex;
public void study(){
System.out.println("studying");
}
public void showAge(){
System.out.println("age: " + age);
}
public int addAge(int i){
age += i;
return age;
}
}
class Person{
int age;
void shout(){
System.out.println("Oh,my god! I am " + age);
}
}
Person p1 = new Person();
执行完后的内存状态。其中类定义如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W9DzcOUD-1689854454303)(https://gitee.com/galloping_pony/img-home/raw/master/%E6%9C%AA%E5%91%BD%E5%90%8D%E7%BB%98%E5%9B%BE.drawio.png)]
class PersonTest{
public static void main(String[] args){
Person p1 = new Person();
Person p2 = new Person();
p1.age = -30;
p1.shout();
p2.shout();
}
}
成员变量 | 局部变量 | |
---|---|---|
声明的位置 | 直接声明在类中 | 方法形参或内部,代码块内,构造器内等 |
修饰符 | private,public,static,final等 | 不能用权限修饰符,可以用final修饰 |
初始化值 | 有默认初始化值 | 没有默认初始化值,必须显式赋值,方可使用 |
内存加载位置 | 堆空间 或 静态空间 | 栈空间 |
格式:
修饰符 返回值类型 方法名(参数类型 形参1, 参数类型 形参2, ...){
方法体程序代码
return 返回值;
}
在同一个类中,允许存在一个以 上的同名方法,只要它们的参数个数或者参数类型不同即可。
重载的特点:与返回值类型无关,只看参数列表,且参数列表必须不同。(参数个数或参数类型)。
调用时,根据方法参数列表的不同来区别。
// 返回两个整数的和
int add(int x, int y){return x+y;}
// 返回三个整数的和
int add(int x,int y,int z){return x+y+z;}
// 返回两个小数的和
double add(double x, double y){return x+y;}
使用案例:
编写程序,定义三个重载方法并调用。方法名为mOL。
三个方法分别接收一个int参数、两个int参数、一个字符串参数。分别执行平方运算并输出结果,相乘并输出结果,输出字符串信息。
在主类的main ()方法中分别用参数区别调用三个方法。
定义三个重载方法max(),第一个方法求两个int值中的最大值,第二个方法求两个double值中的最大值,第三个方法求三个double值中的最大值,并分别调用三个方法。
public class OverloadExer {
// 1. 如下的三个方法构成重载
public void mOL(int i){
System.out.println(i * i);
}
public void mOL(int i,int j){
System.out.println(i * j);
}
public void mOL(String s){
System.out.println(s);
}
//2.如下的三个方法构成重载
public int max(int i,int j){
return (i > j)? i : j;
}
public double max(double d1,double d2){
return (d1 > d2)? d1 : d2;
}
Public double max(double d1,double d2,double d3){
double max = (d1 > d2)? d1 : d2;
return (max > d3)? max : d3;
}
}
//JDK 5.0以前:采用数组形参来定义方法,传入多个同一类型变量
public static void test(int a ,String[] books);
//JDK5.0:采用可变个数形参来定义方法,传入多个同一类型变量
public static void test(int a ,String… books);
public class Test2 {
public void show(String[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
public void display(String... arr) {
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
public void display(String name, int... arr) {
System.out.println("name=" + name);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
public static void main(String[] args) {
Test2 t2 = new Test2();
String[] strs = new String[]{"a", "b", "c"};
t2.show(strs);
System.out.println("--------------");
String[] strs2 = new String[]{"aa", "bb", "cc"};
t2.display(strs2);
System.out.println("--------------");
//可变参数用法
t2.display();
// t2.show(); //报错
System.out.println("--------------");
t2.display("mickey", "a", "b");
t2.display("mickey", 1, 2, 3);
}
}
方法,必须由其所在类或对象调用才有意义。若方法含有参数:
Java里方法的参数传递方式只有一种:值传递。 即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。
递归方法:一个方法体内调用它自身。
public class RecursionTest {
public static void main(String[] args) {
// 例1:计算1-100之间所有自然数的和
// 方式一:
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
System.out.println(sum);
// 方式二:
RecursionTest test = new RecursionTest();
int sum1 = test.getSum(100);
System.out.println(sum1);
System.out.println("*****************");
int value = test.f(10);
System.out.println(value);
}
public int getSum(int n) {// 3
if (n == 1) {
return 1;
} else {
return n + getSum(n - 1);
}
}
public int getSum1(int n) {
if (n == 1) {
return 1;
} else {
return n * getSum1(n - 1);
}
}
}