当前位置: 首页 > news >正文

java 4 (面向对象上)

java——面向对象(上)

目录

  • java——面向对象(上)
    • 面向对象的思想概述
    • 类的成员(1-2):属性和方法
    • 对象的内存解析
    • 类中属性的使用
    • 类中方法的使用
      • 1.举例:
      • 2.声明方法:
      • 3.说明
      • 4.return关键字的使用:
      • 5.方法的使用中,可以调用当前类的属性或方法
      • 实例1:求圆的面积
      • 实例2:打印矩形
      • 实例3:打印学生信息
      • 实例4:对实例三的改进
    • 面向对象的知识点总结
    • 万事万物皆对象
    • 对象数组的内存解析
    • 匿名对象的使用
    • 自定义数组的工具类
    • 再谈方法:方法的重载
    • 再谈方法:可变个数的形参
    • 再谈方法:方法参数的值传递机制
      • 变量的赋值
      • 方法形参的值传递机制
    • 再谈方法:递归方法的使用
      • 实例1:求和
      • 实例2:求阶乘
      • 实例3:应用
      • 实例4:斐波那契数列
    • 阶段性总结
    • 面向对象特征一:封装与隐藏
      • 封装性的引入
      • 封装性的体现
      • 四种权限修饰符
    • 类的成员(3):构造器
      • 构造器的作用:
      • 说明
      • 实例:三角形
    • 总结:属性赋值的先后属性
    • javaBean
    • 关键字:this的使用
    • 关键字:package的使用
    • 关键字:import的使用
    • MVC设计模式

java是一门面向对象的语言

1.java类及类的成员:属性、方法、构造器;代码块、内部类

2.面向对象的三大特征:封装性、继承性、多态性、(抽象性)

3.其它关键字:this、super、static、final、abstract、interface、package、import

面向过程&面向对象

面向过程:强调的是功能行为,以函数为最小单位,考虑怎么做

面向对象:强调具备了功能的对象,以类/对象为最小单位,考虑谁来做

面向对象的思想概述

面向对象的两个要素

**类(Class)**是对一类事物的描述,是抽象的,概念上的定义

**对象(Object)**是实际存在的该类事物的每个个体,因此也称为实例(instance)

设计类就是设计类的成员

类的成员(1-2):属性和方法

常见的类成员:属性、行为(方法)

属性:成员变量------>field/域、字段

方法:成员方法------>函数(C语言)------>method

三步骤:
step1:创建类,设计类的成员
step2:创建类的对象
step3:通过“对象.属性”或“对象.方法”调用对象的结构

class Person{//属性String name;int age;boolean isMale;//方法public void eat() {System.out.println("人可以吃饭");}public void sleep() {System.out.println("人可以睡觉");}public void talk(String language) {System.out.println("人可以说话,使用的是"+language);}
}

当我们创建一个类后,我们怎么使用呢——对象:java的实例化

/*类和对象的使用(面向对象思想落地的实现)
三步骤:
step1:创建类,设计类的成员
step2:创建类的对象
step3:通过“对象.属性”或“对象.方法”调用对象的结构
*/
public class personTest {public static void main(String[] args) {//创建person类的对象//step2:创建类的对象Person p1=new Person();//Scanner scanner=new Scanner(System.in)//调用对象的结构:属性、方法//step3:通过“对象.属性”或“对象.方法”调用对象的结构//调用属性:“对象.属性”p1.name="Tom";p1.isMale=true;System.out.println(p1.name);//调用方法:“对象.方法”p1.eat();p1.sleep();p1.talk("Chinese");}
}//step1:创建类,设计类的成员
class Person{//属性String name;int age;boolean isMale;//方法public void eat() {System.out.println("人可以吃饭");}public void sleep() {System.out.println("人可以睡觉");}public void talk(String language) {System.out.println("人可以说话,使用的是"+language);}
}	

现在我们再创建一个对象

Person p2=new Person();
System.out.println(p2.name);//Tom?   null? 
System.out.println(p2.isMale);//false
Person p3=p1;    //将p1变量保存的对象地址赋值给p3,导致p1和p3指向了堆空间中同一个对象实体
System.out.println(p3.name);//Tom

结果为null,这是什么意思呢?

当我们new了之后,我们就在堆空间申请一片内存空间:当我们创建了一个类的多个对象,则每个对象都独立的拥有一套类的属性(非static);这就意味着:如果我们修改一个对象的属性a,则不影响另外一个对象属性a的值

对象的内存解析

image-20220918162528821

类中属性的使用

属性(成员变量)vs局部变量

1.相同点

​ 1.1定义变量的格式:数据类型 变量名=变量值

​ 1.2先声明、后使用

​ 1.3变量都有其对应的作用域

2.不同点

​ 2.1在类中声明的位置不同

​ 属性:直接定义在类的一对{}内

​ 局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量

​ 2.2关于修饰符的不同

​ 属性:可以在声明属性时,指明其权限,使用权限修饰符

​ 常用的权限修饰符:private、public、缺省、protected—>封装性

​ 目前,大家声明属性时,都使用缺省就可以了

​ 局部变量:不可以使用权限修饰符

​ 2.3默认初始化值的情况:

​ 属性:类的属性根据其类型都有默认初始化值(类比一维数组元素的初始化值)

​ 整型(byte、short、int、long):0

​ 浮点型(float、double):0.0

​ 字符型(char):0

​ 布尔型(boolean):false

​ 引用数据类型(类、数组、接口):null

局部变量:没有默认初始化值

​ 意味着我们调用局部变量前,一定要赋值

​ 特别的,形参在调用时,再赋值即可

2.4在内存中加载的位置:

属性:加载到堆空间中(非static)

局部变量:加载到栈空间

package Class_and_Object;public class UserTest {public static void main(String[] args) {User u1=new User();//下面查看属性的初始化值System.out.println(u1.name);System.out.println(u1.age);System.out.println(u1.isMale);}
}
class User{//属性String name;public int age;boolean isMale;//方法public void talk(String language) {//language是局部变量;这里可以在调用的时候赋值(因为是形参)System.out.println("我们使用"+language+"进行交流");}public void eat() {String food="米饭";//局部变量System.out.println("我们的主食是"+food);}
}

类中方法的使用

方法:描述类应该具有的功能

​ 比如:Math类:sqrt() \random()…

1.举例:

class Customer{//属性String name;int age;boolean isMale;//方法public void eat() {System.out.println("客户吃饭");}public void sleep(int hour) {System.out.println("休息了:"+hour+"小时");}public String getName() {return name;}public String getNation(String nation) {String information="我的国籍是:"+nation;return information;}
}

这里运用到的方法为:

public void eat()

public void sleep(int hour)

public String getName()

public String getNation(String nation)

2.声明方法:

格式:

权限修饰符 返回值类型 方法名(形参列表){    //形参列表根据实际情况不止一个方法体;
}  

3.说明

​ **3.1关于权限修饰符:**默认方法的权限修饰符先都使用public

java规定的四种权限修饰符:private、public、缺省、protected  ------>封装性

​ **3.2返回值类型:**有返回值 vs 没有返回值

​ 3.2.1如果方法有返回值:则必须在方法声明时。指定返回值的类型;同时方法中需要用return关键字来返回返回指定类型的变量或常量;

​ 如果方法没有返回值:则在方法声明时,使用void来表示,通常,没有返回值的方法中,就不用使用return;但是,如果使用return的话,表示结束此方法的意思

​ 3.2.2我们定义方法的时候该不该有返回值?经验主义

​ **3.3方法名:**属于标识符(见名知意)

​ **3.4形参列表:**方法可以声明0个、1个、多个形参

格式:数据类型1 形参1,数据类型2 形参2,......

4.return关键字的使用:

​ (1.使用范围,使用在方法体中

​ (2.作用:结束方法;

​ 针对有返回值类型的方法,使用“return 数据”方法返回所需要的数据

​ (3.注意点:return关键字后面不可以声明执行语句

5.方法的使用中,可以调用当前类的属性或方法

​ 【特殊的】,方法A中又调用了方法A:递归方法

​ 方法中,不可以定义方法

实例1:求圆的面积

public class CircleTest {public static void main(String[] args) {Circle c1=new Circle();c1.radius=2;double area=c1.findArea();System.out.println(area);}
}
class Circle{//属性double radius;       //半径//求圆的面积public double findArea() {double area=3.14*radius*radius;return area;}
}
public class Print_Matrix_class {public static void main(String[] args) {Print_Matrix_class test = new Print_Matrix_class();test.print_methed();}//编写一个能打印*矩形的方法public void print_methed() {for (int i = 1; i <= 10; i++) {for (int j = 1; j <= 8; j++) {System.out.print("*");}System.out.println();}}
}

注意括号的包含关系 print_methed()这个方法是包含在public class 类当中的,相当于是整个文件的大类,因此我们在使用方法时仍然需要创建实例化对象:Print_Matrix_class test = new Print_Matrix_class();其中的test就是我们所创造的对象

实例2:打印矩形

public class Print_Matrix_class {public static void main(String[] args) {Print_Matrix_class test = new Print_Matrix_class();int area=test.print_methed();//方式1:System.out.println("面积为:"+area);//方式2:System.out.println(test.print_methed());}//编写一个能打印*矩阵的方法public int print_methed() {for (int i = 1; i <= 10; i++) {for (int j = 1; j <= 8; j++) {System.out.print("*");}System.out.println();}//System.out.println(10*8);return 10*8;	}
}
System.out.println(test.print_methed());

对于这段语句,输出语句也可以在括号内使用【方法】,这里将方法看作成了一个变量,变量的值即是该方法的返回值(该类调用方法不会报错)

public class Print_Rectangle_class02 {public static void main(String[] args) {Print_Rectangle_class02 test = new Print_Rectangle_class02();int result=test.method(5, 5);//方法1:System.out.println(result);//方法2:System.out.println(test.method(5, 5));}public int method(int m, int n) {for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {System.out.print("*");}System.out.println();}return m*n;}
}

实例3:打印学生信息

public class Students_class {public static void main(String[] args) {// 声明20个对象// student s1=new student(); //太多了// 声明student类型的数组student[] stu = new student[20]; // 对象数组for (int i = 0; i < 20; i++) {// 给数组元素赋值stu[i] = new student();// 给student对象属性赋值stu[i].number = i + 1;// 年级在1-6之间取随机数stu[i].state = (int) (Math.random() * (6 - 1 + 1) + 1);// 成绩在0-100范围stu[i].score = (int) (Math.random() * (100 - 0 + 1) + 1);}// 遍历学生数组for (int i = 0; i < stu.length; i++) {// System.out.println(stu[i]); 输出的结果为地址// 对于这类引用类型的变量,不是null那么就存地址// 这里因为stu已经new了,那么它就已经不是null了// 如果我们需要打印出值,我们需要引用它System.out.println(stu[i].number + "," + stu[i].state + "," +stu[i].score);}// 使用方法来实现// 方法1:for (int j = 0; j < stu.length; j++) {String info = stu[j].Studentinfo();System.out.println(info);}// 方法2:for (int j = 0; j < stu.length; j++) {System.out.println(stu[j].Studentinfo());}//打印出state3年级学生的成绩for (int j = 0; j < stu.length; j++) {if(stu[j].state==3) {System.out.println(stu[j].Studentinfo());}}//使用冒泡排序队学生成绩排序for(int i=0;i<stu.length-1;i++) {        //控制每一大轮for(int j=0;j<stu.length-1-i;j++) {  //控制每一轮中的交换if(stu[j].score>stu[j+1].score) {student temp=stu[j];stu[j]=stu[j+1];stu[j+1]=temp;}}}for (int i = 0; i < stu.length; i++) {System.out.println(stu[i].number + "," + stu[i].state + "," +stu[i].score);}}
}class student {// 属性int number; // 学号int state; // 年级int score; // 成绩// 方法// 显示学生信息public String Studentinfo() {return "学号" + number + "年级" + state + "成绩" + score;}
}

【注意】:在冒泡排序中我们需要注意的是,我们定义临时变量时不要忘记变量类型是student

student temp=stu[j];

然后就是在交换时,错误的写法是:

student temp.score=stu[j];
stu[j].score=stu[j+1].score;
stu[j+1].score=temp;

因为如果只对score进行交换那么该学生的成绩即是别人的成绩了,因此在交换时要交换的是这个学生的整个属性

实例4:对实例三的改进

将操作数组的功能封装到方法中

public class Students_class02 {public static void main(String[] args) {// 声明20个对象// student s1=new student(); //太多了// 声明student类型的数组student1[] stu = new student1[20]; // 对象数组for (int i = 0; i < 20; i++) {// 给数组元素赋值stu[i] = new student1();// 给student对象属性赋值stu[i].number = i + 1;// 年级在1-6之间取随机数stu[i].state = (int) (Math.random() * (6 - 1 + 1) + 1);// 成绩在0-100范围stu[i].score = (int) (Math.random() * (100 - 0 + 1) + 1);}Students_class02 test=new Students_class02 ();     //在Students_class02 中造了方法,我们在使用前需要new一个对象test.traverse_print(stu);test.searchState(stu,6);test.sort(stu);}//遍历public void traverse_print(student1[] stu) {for (int i = 0; i < stu.length; i++) {System.out.println(stu[i].number + "," + stu[i].state + "," + stu[i].score);}}//选择年级public void searchState(student1[] stu, int state) {for (int j = 0; j < stu.length; j++) {if (stu[j].state == state) {System.out.println(stu[j].Studentinfo());}}}//按成绩排序public void sort(student1[] stu) {for (int i = 0; i < stu.length - 1; i++) { // 控制每一大轮for (int j = 0; j < stu.length - 1 - i; j++) { // 控制每一轮中的交换if (stu[j].score > stu[j + 1].score) {student1 temp = stu[j];stu[j] = stu[j + 1];stu[j + 1] = temp;}}}}
}
class student1 {// 属性int number; // 学号int state; // 年级int score; // 成绩// 方法// 显示学生信息public String Studentinfo() {return "学号" + number + "年级" + state + "成绩" + score;}	
}

面向对象的知识点总结

1.面向对象思想编程内容的三条主线是什么

​ a.类及类的成员:属性、方法、构造器、代码块、内部类

​ b.面向对象的三大特征:封装、继承、多态

​ c.其它关键字:this,super,abstract,interface,static,final,package,import

面向对象的编程思想?

2.面向对象中类和对象的理解:对象是类的实例化(对象是由类new出来的)

​ 类:抽象的、概念上的内容

​ 对象:实实在在存在的一个个体(在内存中真正占据空间)

3.类和对象的创建和执行操作的三步

创建类------>类的实例化------>调用对象的结构:“对象.属性” “对象.方法”

4.内存分配情况

img

5.面向过程:功能行为,以函数为最小单位

​ 面向对象:强调了具备了功能的对象

6.内存解析说明

preson p1=new person();
preson p2=new person();
preson p3=p1;    //没有新建一个对象,共用一个堆空间

JVM(java虚拟机)内存结构

编译完源程序以后,生成一个或多个字节码文件,我们使用JVM类的加载器和解释器对生成的字节码文件进行解释运行。意味着,需要将字节码文件对应的类加载到内存中,涉及到内存解析

我们将new出来的结构(比如:数组、对象)加载到空间中。补充:对象的属性(非static的)加载到堆空间中

万事万物皆对象

1.在Java语言范畴中,我们都将功能结构等封装到类中,通过类的实例化,来调用具体的功能结构

2.涉及到java语言与前端HTML、后端数据库交互时,前后端结构在java层面交互时,都体现为类、对象

​ Scanner,String等

​ 文件、File

​ 网络资源,URL

对象数组的内存解析

img

匿名对象的使用

代码引入:

public class Anonymous_Objects {public static void main(String[] args) {Phone p=new Phone();//p=null;System.out.println(p);    //带类型的地址p.playGame();p.sendEmail();  //有名字的对象:p(对象名)//匿名对象new Phone().sendEmail();new Phone().playGame();   //这两个用的就不是一个对象了(每new一个就是一个新对象)new Phone().price=1999;new Phone().showPrice();  //0.0(double类型,再次说明不是同一对象了)}
}
class Phone{double price;public void sendEmail() {System.out.println("发送邮件");}public void playGame() {System.out.println("玩游戏");}public void showPrice() {System.out.println(price);}
}

理解:

1.我们创建的对象,没有显示的赋给一个变量名,即为匿名对象

2.特征:匿名对象只能调用一次

3.使用:如下

class PhoneMall{public void showPhone(Phone iphone) {  //iphone.sendEmail();iphone.playGame();}
}PhoneMall p2=new PhoneMall();
p2.showPhone(new Phone());//匿名对象(new一个Phone类型的对象,只使用这一次)

自定义数组的工具类

通过上述的代码,我们体会到了将具体的思路封装到方法中,在我们使用的时候只需要调用这个方法即可,给我们程序带来了极大的方便,因此我们可以试着将数组的一系列方法也给包装到方法中去

//自定义数组工具类
public class Custom_Array_Tool_Class {// 求数组的最大值public int getMax(int[] arr) {int maxValue = arr[0];for (int i = 0; i < arr.length; i++) {if (maxValue < arr[i]) {maxValue = arr[i];}}return maxValue;}// 求数组的最小值public int getMin(int[] arr) {int minValue = arr[0];for (int i = 0; i < arr.length; i++) {if (minValue > arr[i]) {minValue = arr[i];}}return minValue;}// 求数组的总和public int getSum(int[] arr) {int sum = 0;for (int i = 0; i < arr.length; i++) {sum += arr[i];}return sum;}// 求数组的平均值public double getAverage(int[] arr) {int sum = 0;for (int i = 0; i < arr.length; i++) {sum += arr[i];}double averageValue = (sum * 1.0) / arr.length;return averageValue;}// 反转数组public void flipsArray(int[] arr) {for (int i = 0; i < arr.length / 2; i++) {int temp = arr[i];arr[i] = arr[arr.length - 1 - i];// 这里需要注意数组下标为arr.length-1代表的是最后一个元素arr[arr.length - 1 - i] = temp;}}// 复制数组public void copyArray(int[] arr) {int[] arr_copy = new int[arr.length];for (int i = 0; i < arr.length; i++) {arr_copy[i] = arr[i];}}// 数组排序public void sortArray(int[] arr) {for (int i = 0; i < arr.length; i++) {for (int j = 0; j < arr.length - 1 - i; j++) {if (arr[j] < arr[j + 1]) {int tem = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tem;}}}}// 遍历数组public void throughArray(int[] arr) {for (int i = 0; i < arr.length; i++) {System.out.print(arr[i] + "\t");}}// 查找指定元素(线性查找)public int searchElement(int[] arr, int target) {for (int i = 0; i < arr.length; i++) {        //这样就不用像之前那样再定义布尔变量啥的了if (target == arr[i]) {return i;}}return -1;//返回负数代表没找到}
}

测试:(使用)

//使用我们自定义的数组工具Custom_Array_Tool_Class
public class Use_My_Arraytools {public static void main(String[] args) {Custom_Array_Tool_Class tool=new Custom_Array_Tool_Class();      //对象是类的实例化int[]arr=new int[]{32,45,67,44,-11,22,78,100,-56,-99,28};int max=tool.getMax(arr);System.out.println("最大值为:"+max);int min=tool.getMin(arr);System.out.println("最小值为:"+min);//等等}
}

再谈方法:方法的重载

1.概念:在同一个类中,允许在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可

​ 两同一不同:同一个类、相同方法名

​ 参数列表不同;参数个数不同;参数类型不同

2.举例:Arrays类中重载的sort()/binarySearch()

​ 调用System.out.println()方法就是经典的方法的重载

3.判断是否重载:

​ 跟方法的权限修饰符、返回值类型、形参变量名、方法都没有关系

4.在通过对象调用方法时,如何确定某一个指定方法:

​ 方法名------>参数列表

再谈方法:可变个数的形参

1.jdk5.0新增的内容

2.具体使用

​ 2.1格式

public void show(String ... strs){System.outy.println("show(String ... strs)");
}

​ 2.2当调用可变个数形参方法时,传入的参数个数可以是0个、1个、2个…

​ 2.3可变个数形参的方法与本类中方法名相同,形参不同的方法直接构成重载

​ 2.4可变个数形参的方法与本来中方法名相同,形参类型也相同的数组之间不构成重构(换句话说:二者不能共存)

意思是两者可以相互的取代

public void show(String ... strs){System.outy.println("show(String ... strs)");
}
public void show(String[] strs){System.outy.println("show(String ... strs)");
}

并且在调用时两者也可以相互的表示

test.show(new String[]{"AA","BB","CC"});
test.show("AA","BB","CC");

因此我们可以理解为:系统对于可变个数的形参,仍然是把它当作一个数组,但是相比数组来说书写更简单

​ 2.5可变个数形参在方法的形参中,必须声明在末尾

public void show(int i,String ... strs);   //right
public void show(String ... strs,int i);   //wrong

​ 2.6可变个数形参在方法的形参中,最多只能声明一个可变形参

再谈方法:方法参数的值传递机制

变量的赋值

public class Value_of_Method {public static void main(String[] args) {// 对于引用数据类型的值传递Order o1 = new Order();o1.OrderId = 1;Order o2 = o1;System.out.println("o1.OrderId=" + o1.OrderId + "\t" + "o2.OrderId=" + o2.OrderId);o2.OrderId = 2;System.out.println("o1.OrderId=" + o1.OrderId + "\t" + "o2.OrderId=" + o2.OrderId);}
}class Order {int OrderId;
}

运行结果如下:

image-20220920160953365

分析:赋值以后,对于引用数据变量类型来说,o1和o2的地址值相同,都指向了堆空间中同一个对象实体

关于变量的赋值:

1.如果变量是基本数据类型,此时赋值的是变量所保存的数据值

2.如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值

方法形参的值传递机制

1.形参:方法定义时,声明的小括号内的参数

实参:方法调用时,实际传递给形参的数据

2.值传递机制

引入:

public class Value_Transfer02 {public static void main(String[] args) {int m=10;int n=20;System.out.println("m="+m+",n="+n);//交换两个变量//int temp=m;//m=n;//n=temp;//交换的操作很常用,我们不妨将此封装到方法中Value_Transfer02 useSwap=new Value_Transfer02();useSwap.Swap(m,n);System.out.println("m="+m+",n="+n);}public void Swap(int m,int n){int temp=m;m=n;n=temp;}
}

运行结果如下:

image-20220920162605973

我们发现并未达到我们的交换的目的!

通过内存来理解:

img

造成原因:如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值

img

因此:如果变量是引用数据类型,此时赋值的变量所保存的数据的地址值

运用到数组上:

public class Arraysorting_class {public static void main(String[] args) {int[] arr=new int[] {-12,22,45,-87,-22,56,78,23,-66};Arraysorting_class arrnum=new Arraysorting_class();for(int i=0;i<arr.length;i++) {for(int j=0;j<arr.length-1-i;j++) {if(arr[j]<arr[j+1]) {arrnum.Swap(arr, i, j);}}}for(int i=0;i<arr.length;i++) {System.out.print(arr[i]+" ");}}public void Swap(int[] arr,int i,int j) {int tem=arr[j];arr[j]=arr[j+1];arr[j+1]=tem;}
}

【总结】:值传递机制

​ 如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值

​ 如果变量是引用数据类型,此时赋值的变量所保存的数据的地址值

实例:

public class UseClass_Circle {//main方法public static void main(String[] args) {PassObject Use=new PassObject();Circle c=new Circle();Use.printAreas(c, 5);System.out.println("now radius is:"+c.radius);}
}
//输出半径和对应的圆面积
public class PassObject {public void printAreas(Circle c, int time) {//在这里已经定义了一个Circle类型的形参c了System.out.println("Radius\t\tArea");for (int i = 1; i <= time; i++) {c.radius = i;// 不用匿名对象double area = c.findArea();System.out.println(c.radius + "\t\t" + area);// 用匿名对象// System.out.println(c.radius + "\t\t" + c.findArea());}c.radius = time + 1;}
}
//Circle类
class Circle {double radius;public double findArea() {return 3.14 * radius * radius;}
}

再谈方法:递归方法的使用

1.递归方法:一个方法体内调用它自身

2.方法的递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无需控制循环;递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环

实例1:求和

public class Recursion_Test {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);Recursion_Test Test=new Recursion_Test();int Result=Test.getSum(100);System.out.println(Result);//System.out.println(Test.getSum(100));//匿名对象}//递归方法public int getSum(int n){//前n个数求和等于前n-1个数求和加上第n个数if(n==1) {return 1;}else {return n+getSum(n-1);}}
}

同理的,我们可以写出n的阶乘的计算

实例2:求阶乘

public int getFactorial(int n){if(n==1) {return 1;}else {return n*getFactorial(n)}}
}

实例3:应用

已知有一个数组:f(0)=1,f(1)=4,f(n+2)=2*f(n+1)+f(n),其中n是大于0的整数,求f(10)的值

//已知有一个数组:f(0)=1,f(1)=4,f(n+2)=2*f(n+1)+f(n),其中n是大于0的整数,求f(10)的值
public class Recursion_Test2 {public static void main(String[] args) {Recursion_Test2 Use = new Recursion_Test2();int Result = Use.getNum(10);System.out.println(Result);}public int getNum(int n) {if (n == 0) {return 1;} else if (n == 1) {return 4;} else {return 2 * getNum(n - 1) + getNum(n - 2);// f(n+2)=2*f(n+1)+f(n)--->f(n)=2*f(n-1)+f(n-2)}}
}

实例4:斐波那契数列

//斐波那契数列
public class Recursion_Test3 {public static void main(String[] args) {Recursion_Test3 Use=new Recursion_Test3();System.out.println(Use.Fibonacci(10));}public int Fibonacci(int n) {if(n==1) {return 1;}else if(n==2) {return 1;}else {return Fibonacci(n-1)+Fibonacci(n-2);}}
}

阶段性总结

1.什么是方法的重载?

​ 两同一不同:同一个类、相同方法名

​ 参数列表不同;参数个数不同;参数类型不同

------>如何调用一种确定的方法:方法名------>参数列表

方法的重载和重写的区别?:没什么关系

2.java方式中参数传递机制的继续体现

​ 如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值

​ 如果变量是引用数据类型,此时赋值的变量所保存的数据的地址值(含变量的数据类型)

3.成员变量和局部变量

4.return关键字的使用:结束方法、针对于有返回值的方法:return+返回数据

5.内存结构:栈(局部变量)、堆(new出来的结构:对象(成员变量)、数组)

面向对象特征一:封装与隐藏

封装性的引入

我们程序设计追求:“高内聚,低耦合”

高内聚:类的内部数据操作细节自己完成,不允许外部干涉

低耦合:仅对外暴露少量的方法用于使用

隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想

引入:当我们创建一个类的对象后,我们可以通过“对象.属性”的方式,对对象的属性进行赋值。这里,赋值操作要受到属性的数据类型和存储范围的制约。除此之外,没有其它制约条件;但是在实际问题中,我们往往要给属性赋值加入额外的限制条件。这个条件就不能在属性声明时体现,我们只能通过方法进行限制条件的添加。(比如,setLegs,同时我们要避免用户再使用"对象.属性“的方式对属性进行赋值。则需要将属性声明为私有的(private),此时针对于属性就体现了封装性

public class Animal_Test {public static void main(String[] args) {Animal a=new Animal();a.name="Peter";a.age=2;a.setLegs(4);a.show();//a.legs=-4;    //虽然我们设计了方法setLegs能对输入的不合法数据进行辨析,但是我们							仍然能通过访问属性来修改legs的值//因此我们将属性legs设为一个私有属性:private,就不能在修改了}
}
class Animal{String name;int age;private int legs;  //腿的个数public void eat() {System.out.println("动物吃东西");}public void show() {System.out.println("name="+name+",age="+age+",legs="+legs);}//对属性的设置public void setLegs(int l) {if(l>=0&&l%2==0) {legs=l;}else {legs=0;}}//对属性的获取public int getLegs() {return legs;}
}

封装性的体现

我们将类的属性私有化(private),同时,提供公共的(public)方法来获取(getXxx)和设置(setXxx);这样的话:

a.legs=4;     //wrong

四种权限修饰符

封装性的体现,需要权限修饰符来配合

1.java规定的四种权限(从小到大排列):

private、缺省、protected、public

缺省的意思就是什么都没有写

image-202209211352522252.四种权限可以修饰类及类的内部结构:属性、方法、构造器、内部类

3.具体的,4种权限都可以用来修饰类的内部结构:属性、方法、构造器、内部类

修饰类的话,只能用:缺省、public

总结封装性:java提供了四种权限修饰来修饰类及类的内部结构,体现类及类的内部结构在被调用时的可见性的大小

类的成员(3):构造器

任何一个类都有构造器(Constructor)

类的前两个成员:属性和方法

构造器的作用:

1.创建对象(new对象时new接的都是构造器)

2.初始化对象的属性

//创建对象
public class PersonTest {public static void main(String[] args) {//创建类的对象:new+构造器Person p=new Person();  //Person():构造器p.eat();}
}
class Person{//属性String name;int age;//方法public void eat() {System.out.println("人可以吃饭");}public void sleep() {System.out.println("人可以睡觉");}
}

说明

1.如果没有显式的定义类的构造器的话,则系统默认提供一个空参的构造器

2.定义构造器的格式:

权限修饰符 类名(形参列表){    //构造器名与类同名}
class Person{//属性String name;int age;//构造器//作用1:创建对象public Person() {System.out.println("已被调用");}//作用2:给对象进行初始化public Person(String s){name=s;}//方法public void eat() {System.out.println("人可以吃饭");}public void sleep() {System.out.println("人可以睡觉");}
}

3.一个类种定义多个构造器,彼此构成重载

4.一旦我们显示定义了类的构造器之后,系统就不再提供默认的空参构造器

5.一个类中,至少会有一个构造器(默认/自己写的)

实例:三角形

public class TriangleTest {public static void main(String[] args) {Triangle t1=new Triangle();t1.setBase(2.0);t1.setHight(2.4);//t1.base=2.5;     wrong:private(存在但不可见)System.out.println("base:"+t1.getBase()+",hight:"+t1.getHight());//通过构造器的初始化Triangle t2=new Triangle(4.0,2.5);System.out.println("base:"+t2.getBase()+",hight:"+t2.getHight());}
}
public class Triangle {private double base;    //底private double hight;   //高//构造器public Triangle() {//空参}public Triangle(double b,double h) {base=b;hight=h;}public void setBase(double b) {base=b;}public double getBase() {return base;}public void setHight(double h) {hight=h;}public double getHight() {return hight;}
}

总结:属性赋值的先后属性

1.默认初始化

2.显式初始化

3.构造器中赋值

4.通过“对象.方法”(封装性)或“对象.属性”赋值

以上操作的先后顺序: 1------>2------>3------>4

javaBean

javaBean是一种Java语言写成的可重用组件

所谓javaBean,是指符合如下标准的java类:

类是公开的
一个无参的公共的构造器
有属性,且有对应的get、set方法
//javaBean
public class customer2 {   //类是公开的private int id;private String name;public customer2() {//一个无参的公共的构造器}//有属性,且有对应的get、set方法public void setId(int i) {id = i;}public int getId() {return id;}public void setName(String s) {name = s;}public String getname() {return name;}
}

关键字:this的使用

this关键字的使用:

1.this可以用来修饰:属性、方法、构造器

2.this理解为:当前对象

​ 2.1在类的方法中,我们可以使用"this.属性"或"this.方法"的方式,调用当前对象属性或方法。但是,通常情况下,我们都选择省略"this."。特殊情况下,如果方法的形参和类的属性同名时,我们必须显式的使用"this.变量"的方式,表面此变量是属性,而非形参

​ 2.2在类的构造器中,我们可以使用"this.属性"或"this.方法"的方式,调用当前对象属性或方法。但是,通常情况下,我们都选择省略"this."。特殊情况下,如果构造器的形参和类的属性同名时,我们必须显式的使用"this.变量"的方式,表面此变量是属性,而非形参

实例:account

public class Account {//属性private int id;     //账号private double balance; //余额private double annualInterestRate; //年利率//构造器public Account(int id,double balance,double annualInterestRate) {this.id=id;this.balance=balance;this.annualInterestRate=annualInterestRate;}//get/set方法:Sourcepublic int getId() {return id;}public void setId(int id) {this.id = id;}public double getBalance() {return balance;}public void setBalance(double balance) {this.balance = balance;}public double getAnnualInterestRate() {return annualInterestRate;}public void setAnnualInterestRate(double annualInterestRate) {this.annualInterestRate = annualInterestRate;}//取钱public void withdraw(double amount) {if(balance<amount) {System.out.println("余额不足");}else {System.out.println("成功取出"+amount+"元");}}public void deposit(double amount) {if(amount>0) {balance+=amount;System.out.println("成功存入:"+amount+"元");}}
}
public class Customer {private String firstName;private String lastName;private Account account;     //在属性中出现自定义类型的变量(引用数据类型)//构造器public Customer(String f,String l) {this.firstName=f;this.lastName=l;}//get-setpublic String getFirstName() {return firstName;}public void setFirstName(String firstName) {this.firstName = firstName;}public String getLastName() {return lastName;}public void setLastName(String lastName) {this.lastName = lastName;}public Account getAccount() {return account;}public void setAccount(Account account) {this.account = account;}
}
public class Test {public static void main(String[] args) {Customer c=new Customer("peter","smith");         //先实例化一个客户Account a=new Account(1000, 2000, 0.0123);        //再为它创建一个账户c.setAccount(a);                                  //这样这个账户就是这个客户的了    //可以连续.(访问)c.getAccount().deposit(100);   //存入100c.getAccount().withdraw(1000); //取出1000c.getAccount().withdraw(50);}
}

【总结】:

1.关联关系:在属性中出现自定义类型的变量(引用数据类型)

2.对象数组(定义多个变量,本身就输入引用类型,也可以作为属性出现)

3.连续操作

c.getAccount().deposit(100);  
c.getAccount().withdraw(1000); 
c.getAccount().withdraw(50);

注意的是,前面的方法一定是有返回值,形成新的对象,再调用下一个属性或方法

关键字:package的使用

1.为了更好的实现项目中类的管理,提供包的概念

2.使用package声明类或接口所属的包,声明在源文件的首行

image-20220926111314185

3.包,属于标识符,遵循标识符的命名规则、规范、见名知意

4.每"."一次就代表一层文件目录

补充:同一个包下,不能命名同名的接口、类

​ 不同的包下,可以命名同名的接口、类

关键字:import的使用

import:导入

1.在源文件中显式的使用import结构导入指定包下的类、接口

2.声明在包的声明和类的声明之间

3.如果需要导入多个结构,则并列写出即可

4.可以用“xxx.*”的方式,表示可以导入xxx包下的所有结构

//并列写出
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
//或者:
import java.util.*;

5.如果使用的类或接口是java.lang包下定义的,则可以省略import结构

6.如果使用的类或接口是本包下定义的,则可以省略import结构

7.如果在源文件中,使用了不同包下的同名的类,必须至少一个类使用全类名的方式显式

8.使用“xxx.*”的方式表面可以调用xxx包下的所有结构。但是如果使用的是xxx子包下的结构,则仍需要显式导入

9.import static:导入指定类或接口中静态结构(属性或方法)

MVC设计模式

image-20220926115203778

相关文章:

java 4 (面向对象上)

java——面向对象&#xff08;上&#xff09; 目录java——面向对象&#xff08;上&#xff09;面向对象的思想概述类的成员&#xff08;1-2&#xff09;&#xff1a;属性和方法对象的内存解析类中属性的使用类中方法的使用1.举例&#xff1a;2.声明方法&#xff1a;3.说明4.re…...

HTTP报头的2个方法

在采集网页信息的时候&#xff0c;经常需要伪造报头来实现采集脚本的有效执行 下面&#xff0c;我们将使用urllib2的header部分伪造报头来实现采集信息 方法1、 #!/usr/bin/python -- coding: utf-8 -- #encodingutf-8 #Filename:urllib2-header.py import urllib2 import…...

yolov5双目检测车辆识别(2023年+单目+双目+python源码+毕业设计)

行人识别yolov5和v7对比yolo车距源码:yolov5双目检测车辆识别(2023年单目双目python源码毕业设计)上盒岛APP&#xff0c;开线上盲盒商店http://www.hedaoapp.com/yunPC/goodsDetails?pid4132 为了提高传统遗传算法(genetic algorithm, GA)IGA优化BP网络迭代时间过长以及精度偏…...

华为OD机试题,用 Java 解【用户调度问题】问题

华为Od必看系列 华为OD机试 全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典使用说明 参加华为od机试,一定要注意不…...

根据mybatis plus注解动态创建sqlite表和表字段

根据mybatis plus注解动态创建sqlite表和表字段 启动时动态创建sqlite数据库&#xff0c;根据mybatis plus注解动态创建表。如果有新增字段&#xff0c;动态创建字段。 文章目录根据mybatis plus注解动态创建sqlite表和表字段一、初始化数据库1.系统启动时初始化数据库2.初始化…...

同步、异步ETL架构的比较

背景介绍&#xff1a; 数据的抽取&#xff0c;转换和加载 (ETL, Extract, Transform, Load) 是构建数据仓库过程中最复杂也是至 关重要的一个步骤&#xff0c;我们通常用两种办法来处理 ETL 流程: 一种是异步(Asynchronous) ETL 方式, 也称为文本文件(Flat file)方式。 另外…...

【机会约束、鲁棒优化】具有排放感知型经济调度中机会约束和鲁棒优化研究【IEEE6节点、IEEE118节点算例】(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

用Python帮老叔选出好基金,大赚一笔,老叔专门提着茅台登门道谢

我有个老叔很喜欢买基金&#xff0c;因为不想被割韭菜&#xff0c;所以啥群都没进&#xff0c;全部自己精挑细选。 看着他的一个本子密密麻麻地写了一大堆东西&#xff0c;全是基金的数据分析&#xff0c;一大把年纪了挺不容易的&#xff0c;于是就决定帮他一把。 在跟他详谈…...

ZeroTier实现内网穿透详细教程,无需公网IP,实现异地组网

ZeroTier实现内网穿透详细教程&#xff0c;无需公网IP&#xff0c;实现异地组网ZeroTier1.官网注册账号&#xff0c;创建自己的局域网段2.点击创建好的网络&#xff0c;进入设置界面进行设置3.下载客户端&#xff0c;安装客户端&#xff0c;然后连接到网络中4.加入网络成功后&a…...

电商 SaaS 全渠道实时数据中台最佳实践

摘要&#xff1a;本文整理自聚水潭数据专家张成玉&#xff0c;聚水潭高级数据工程师应圣楚&#xff0c;在 FFA 2022 行业案例专场的分享。本篇内容主要分为四个部分&#xff1a;实时数仓的建设和发展数据中台的产品体系及架构实时计算的实践和优化对实时计算的未来展望Tips&…...

macos ncnn 安装踩坑记录···

安装真麻烦踩了无数坑&#xff0c;官方给的安装教程&#xff1a;macos安装ncnn, 安装过程老是报错&#xff0c;记录一下卡的比较久的&#xff0c;网上也不好找资料的错. 我的电脑&#xff1a; 1. 使用homebrew 的时候失败fatal: not in a git directory Error: Command failed…...

ESP32设备驱动-AM2301(DHT21)温度湿度传感器驱动

AM2301(DHT21)温度湿度传感器驱动 文章目录 AM2301(DHT21)温度湿度传感器驱动1、AM2301(DHT21)介绍2、硬件准备3、软件准备4、驱动实现1、AM2301(DHT21)介绍 AM2301 湿敏电容数字温湿度模块是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温…...

[数据结构]:16-归并排序(顺序表指针实现形式)(C语言实现)

目录 前言 已完成内容 归并排序实现 01-开发环境 02-文件布局 03-代码 01-主函数 02-头文件 03-PSeqListFunction.cpp 04-SortFunction.cpp 结语 前言 此专栏包含408考研数据结构全部内容&#xff0c;除其中使用到C引用外&#xff0c;全为C语言代码。使用C引用主要是…...

React(七):Router基本使用、嵌套路由、编程式导航、路由传参、懒加载

React&#xff08;七&#xff09;一、React-Router的基本使用1.安装和介绍2.路由的配置和跳转3.Navigate的使用4.如果找不到对应的路由路径&#xff1f;二、嵌套路由的用法三、编程式路由导航1.类组件中使用useNavigate2.函数式组件中使用useNavigate四、路由跳转传参1.设置好路…...

Java基础面试题(一)

Java基础面试题 一、面向对象和集合专题 1. 面向对象和面向过程的区别 面向过程&#xff1a;是分析解决问题的步骤&#xff0c;然后用函数把这些步骤一步一步地实现&#xff0c;然后在使用的时候一一调用则可。性能较高&#xff0c;所以单片机、嵌入式开发等一般采用面向过程…...

代码命名规范是一种责任也是一种精神(工匠精神)

代码命名规范之美规范概述命名规范管理类命名BootstrapProcessorManagerHolderFactoryProviderRegistrarEngineServiceTask传播类命名ContextPropagator回调类命名Handler &#xff0c;Callback&#xff0c;Trigger&#xff0c;ListenerAware监控类命名MetricsEstimatorAccumul…...

奇淫技巧:阅读源码时基于一组快捷键,让我们知道身在何方!

一个十分蛋疼的问题 在我们阅读框架底层源码的时候&#xff0c;我们往往会一个方法一个方法的往下翻&#xff0c;翻了很久很快就会有这样的灵魂拷问&#xff1a;我从那个类&#xff08;方法&#xff09;来&#xff0c;我要到哪个&#xff08;类&#xff09;方法中去。这个时候…...

你真的弄懂this指向了吗

前言 在说 this 指向之前&#xff0c;请观察以下代码&#xff0c;并说出它们的输出结果&#xff1a; 第 1 组&#xff1a;标准函数 window.color "red"; let o {color: "blue", }; function sayColor() {console.log(this.color); }sayColor(); // 输…...

阿里云服务器使用教程:使用xshell、xFtp工具连接阿里云服务器(Centos7)并修改Centos7的yum源为阿里镜像源

目录 1、下载并安装xshell、xFtp 2、远程连接阿里云服务器 3、 修改Centos7的yum源为阿里镜像源 1、下载并安装xshell、xFtp XShell可以在Windows界面下来访问远端不同系统下的服务器&#xff0c;从而比较好的达到远程控制终端的目的。它支持 RLOGIN、SFTP、SERIAL、TELNET、…...

一文快速入门 HTML 网页基础

专栏简介: 前端从入门到进阶 题目来源: leetcode,牛客,剑指offer. 创作目标: 记录学习JavaEE学习历程 希望在提升自己的同时,帮助他人,,与大家一起共同进步,互相成长. 学历代表过去,能力代表现在,学习能力代表未来! 目录 1.HTML 结构 1.1. 认识 HTML 标签 1.2 HTML 文件结构…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

学校招生小程序源码介绍

基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码&#xff0c;专为学校招生场景量身打造&#xff0c;功能实用且操作便捷。 从技术架构来看&#xff0c;ThinkPHP提供稳定可靠的后台服务&#xff0c;FastAdmin加速开发流程&#xff0c;UniApp则保障小程序在多端有良好的兼…...

质量体系的重要

质量体系是为确保产品、服务或过程质量满足规定要求&#xff0c;由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面&#xff1a; &#x1f3db;️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限&#xff0c;形成层级清晰的管理网络&#xf…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

NPOI Excel用OLE对象的形式插入文件附件以及插入图片

static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...

MySQL 主从同步异常处理

阅读原文&#xff1a;https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主&#xff0c;遇到的这个错误&#xff1a; Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一&#xff0c;通常表示&#xff…...