java 4 (面向对象上)

news2024/11/18 1:38:42

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方法:Source
	public 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-set
	public 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);   //存入100
		c.getAccount().withdraw(1000); //取出1000
		c.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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/398512.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机网络基础知识点【1】

文章目录计算机网络第一章 计算机网络参考模型1.计算机网络为什么需要分层&#xff1f;1.1 分层思想1.2 分层好处2.OSI七层模型2.1 OSI七层模型总结2.2 OSI七层工作原理2.3 数据封装与解封装2.4 计算机网络常用协议3.TCP/IP参考模型3.1 什么是TCP/IP协议3.2 TCP/IP协议族的组成…

扬帆优配|引活水 增活力 促转型 创业板助力实体经济高质量发展

立异就是生产力&#xff0c;企业赖之以强&#xff0c;国家赖之以盛。全面注册制变革持续开释立异生机。日前&#xff0c;创业板公司已开端连续公布2022年度年度报告和2023年第一季度成绩预告&#xff0c;从频频传来的“喜报”中可窥见立异驱动开展战略下新兴工业的强劲开展态势…

jvm之堆上的GC和分代思想解读

堆上的GC JVM在进行GC时&#xff0c;并非每次都对上面三个内存区域一起回收的&#xff0c;大部分时候回收的都是指新生代。 性能调优主要就是减少GC&#xff0c;GC线程执行引发STW会让用户线程停止&#xff0c;阻碍了用户线程的执行&#xff0c;并且majorGC和fullGC阻碍的时间…

内卷把同事逼成了“扫地僧”,把Git上所有面试题整理成足足24W字Java八股文

互联网大厂更多的是看重学历还是技术&#xff1f;毫无疑问&#xff0c;是技术&#xff0c;技术水平相近的情况下&#xff0c;肯定学历高/好的会优先一点&#xff0c;这点大家肯定都理解。说实话&#xff0c;学弟学妹们找工作难&#xff0c;作为面试官招人也难呀&#xff01;&am…

TypeScript深度剖析:Vue项目中应用TypeScript?

一、前言 与link类似 在VUE项目中应用typescript&#xff0c;我们需要引入一个库vue-property-decorator&#xff0c; 其是基于vue-class-component库而来&#xff0c;这个库vue官方推出的一个支持使用class方式来开发vue单文件组件的库 主要的功能如下&#xff1a; metho…

【刷题笔记】之滑动窗口(长度最小的子数组、水果成篮、最小的覆盖子串)

滑动窗口模板//滑动窗口模板&#xff1a;注意使用滑动窗口方法&#xff0c;使用一个 for(while) 循环中的变量是用来控制终止位置的//最小滑窗&#xff1a;给定数组 nums&#xff0c;定义滑动窗口的左右边界 i、j&#xff0c;求满足某个条件的滑窗的最小长度 for(j 0; j < …

华为OD机试题,用 Java 解【寻找身高相近的小朋友】问题

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

SpringMVC源码:视图解析器

参考资料&#xff1a; 《SpringMVC源码解析系列》 《SpringMVC源码分析》 《Spring MVC源码》 写在开头&#xff1a;本文为个人学习笔记&#xff0c;内容比较随意&#xff0c;夹杂个人理解&#xff0c;如有错误&#xff0c;欢迎指正。 前文&#xff1a; 《SpringMVC源码&a…

APP线上产品的日志埋点方案

运营运维系列文章 APP线上产品的日志埋点方案 APP日志埋点前言什么是埋点&#xff1f;埋点方案设计事件模型埋点事件上报日志存储平台1. 亚马逊云S32. Kibana博客创建时间&#xff1a;2023.03.08 博客更新时间&#xff1a;2023.03.09 以Android studio build7.0.0&#xff0c…

git stash 暂存减少分支误操作的神器

背景 有时不小心在master或者develop分支上开发了代码&#xff0c;正要提交时才发现自己选错分支了&#xff0c;以前的笨方法是把要提交的代码&#xff0c;一个个记录下来&#xff0c;都保存另外一个文件中去&#xff0c;然后再切换到特性分支中&#xff0c;一个个覆盖到具体的…

问到ThreadLocal,看这一篇就够了|金三银四系列

ThreadLocal 原理和常见问题详解&#xff0c;用来复习准没错&#xff01;点击上方“后端开发技术”&#xff0c;选择“设为星标” &#xff0c;优质资源及时送达ThreadLocal 是什么&#xff1f;ThreadLocal 是线程本地变量。当使用 ThreadLocal 维护变量时&#xff0c;ThreadLo…

高效学 C++|组合类的构造函数

设计好MyString类后&#xff0c;就可以像使用普通类型一样使用它了。例如&#xff0c;类的对象可以像普通的变量一样作为另一个类的数据成员。【例1】 MyString类的对象作为CStudent类的数据成员。1. //MyString类的定义省略 2. //注意&#xff1a;保留其构造函数、析构函数、…

LeetCode——2379. 得到 K 个黑块的最少涂色次数

一、题目 给你一个长度为 n 下标从 0 开始的字符串 blocks &#xff0c;blocks[i] 要么是 ‘W’ 要么是 ‘B’ &#xff0c;表示第 i 块的颜色。字符 ‘W’ 和 ‘B’ 分别表示白色和黑色。 给你一个整数 k &#xff0c;表示想要 连续 黑色块的数目。 每一次操作中&#xff0…

Java 中的拆箱和装箱

在 Java 中&#xff0c;每个基本数据类型都对应了一个包装类型&#xff0c;比如&#xff1a;int 的包装类型是 Integer&#xff0c;double 的包装类型是 Double…那么&#xff0c;基本数据类型和包装类型有什么区别呢&#xff1f; 大概有以下几点区别&#xff1a; 成员变量的…

详解Vue安装与配置(2023)

文章目录一、官网下载node.js二、安装Node.js三、环境配置四、idea导入vue项目五、IDEA添加Vue.js插件一、官网下载node.js Vue是前端开发框架。搭建框架&#xff0c;首先要搭建环境。搭建Vue的环境工具&#xff1a;node.js&#xff08;JavaScript的运行环境&#xff09;&…

【最重要的 G 代码命令列表】

【最重要的 G 代码命令列表】1. 什么是G代码&#xff1f;2. 如何阅读G代码命令&#xff1f;3. 最重要/最常见的 G 代码命令3.1 G00 – 快速定位3.2 G01 – 线性插值3.3 G02 – 顺时针圆形插值3.4 G00、G01、G02 示例 – 手动 G 代码编程3.4 G03 – 逆时针圆形插补3.5 G20/ G21 …

【Unity游戏破解】外挂原理分析

文章目录认识unity打包目录结构游戏逆向流程Unity游戏攻击面可被攻击原因mono的打包建议方案锁血飞天无限金币攻击力翻倍以上统称内存挂透视自瞄压枪瞬移内购破解Unity游戏防御开发时注意数据安全接入第三方反作弊系统外挂检测思路狠人自爆实战查看目录结构用il2cpp dumper例子…

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

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

ArrayList与LinkedList的区别 以及 链表理解

list接口中ArrayList、LinkedList都不是线程安全&#xff0c;Vector是线程安全 1、数据结构不同 ArrayList是Array(动态数组)的数据结构&#xff0c;LinkedList是Link(链表)双向链表的数据结构。 2、空间灵活性 ArrayList最好指定初始容量 LinkedList是比ArrayList灵活的&a…

Noah-MP陆面过程模型建模

【方式】&#xff1a;直播永久回放长期答疑群辅助全套资料【目标】&#xff1a;了解陆表过程的主要研究内容以及陆面模型在生态水文研究中的地位和作用&#xff1b;熟悉模型的发展历程&#xff0c;常见模型及各自特点&#xff1b;理解Noah-MP模型的原理&#xff0c;掌握Noah-MP…