Java 面向对象(上)1 —— 类

目录

 

1 面向对象OOP和面向过程POP

1.1 面向对象的三条主线

1.2 两者区别

1.3 举例:创建第一个类

1.4 内存解析

1.5 类中方法的声明和使用

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

 1.5.2 方法的声明

 1.5.3 说明

1.5.4 return关键字的使用:

 1.5.5 方法的使用中:

1.5 课后练习

1.5.1 写一个类并调用

1.5.2 编写一个可以输出矩阵的方法

1.5.3 编写一个students类

1.5.4 MyDate类

1.6 Day8测试

1.6.1 面向对象思想编程内容的三条主线分别是什么?

1.6.2 谈谈你对面向对象中类和对象的理解,并指出二者的关系?

1.6.3 面向对象思想的体现一:类和对象的创建和执行操作有哪三步?

1.6.4类的方法内是否可以定义变量?是否可以调用属性?是否可以定义方法?是否可以调用方法?

2 面向对象上概念总结

2.1 类与对象

2.1.1 JVM内存结构

2.2 类的结构之一:属性

2.2.1 变量的分类方法

2.3 类的结构之一:方法

 2.3.1.return关键字

3 匿名对象

4 自己写一个数组类

5 再谈方法

5.1 重载

5.2 可变个数的形参

5.3 方法参数的值传递机制

 

string是类 特例

5.3.1 面试题 参数传递

5.3.2 面试题 貌似考参数传递

5.3.3 看似简单实则有坑的题

5.3.4 将对象作为参数传递给方法

5.4 递归

6 方法的课后练习

6.1 什么是方法的重载?

6.2 说明Java方法中的参数传递机制的具体体现?

6.4. 谈谈return关键字的使用


1 面向对象OOP和面向过程POP

1.1 面向对象的三条主线

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

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

其他关键字:this、super、static、final、abstract、interface、package、import

1.2 两者区别

人把大象装进冰箱

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

把冰箱打开、抬起大象塞进冰箱、关门

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

 *人{
 * 		打开(冰箱){
 * 			冰箱.开开();
 * 		}
 * 
 * 		抬起(大象){
 * 			大象.进入(冰箱);
 * 		}
 * 
 * 		关闭(冰箱){
 * 			冰箱.闭合();
 * 		}
 * 
 * }
 * 
 * 
 * 冰箱{
 * 		开开(){}
 * 		闭合(){}
 * }
 * 
 * 大象{
 * 		进入(冰箱){
 * 		}
 * }

方便之处:拓展功能

两个要素:

 * 类:对一类事物的描述,是抽象的、概念上的定义
 * 对象:是实际存在的该类事物的每个个体,因而也称为实例(instance)
 * >面向对象程序设计的重点是类的设计
 * >设计类,就是设计类的成员。

1.3 举例:创建第一个类

区分类 对象 属性 方法

/*
 * 一、设计类,其实就是设计类的成员
 * 
 *  属性 = 成员变量 = field = 域、字段
 *  方法 = 成员方法 = 函数 = method
 * 
 *  创建类的对象 = 类的实例化 = 实例化类
 * 
 * 二、类和对象的使用(面向对象思想落地的实现):
 *  1.创建类,设计类的成员
 *  2.创建类的对象
 *  3.通过“对象.属性”或“对象.方法”调用对象的结构
 *  
 * 三、如果创建了一个类的多个对象,则每个对象都独立的拥有一套类的属性。(非static的)
 *   意味着:如果我们修改一个对象的属性a,则不影响另外一个对象属性a的值。
 *   
 * 四、对象的内存解析
 */
//测试类
public class PersonTest {
	public static void main(String[] args) {
		//2.创建Person类的对象
		Person p1 = new Person();//为啥要重复写两个Person
		//Scanner scannner = new Scanner(System.in);
		
		//调用对象的结构:属性、方法
		//调用属性:"对象.属性"
		p1.name = "Tom";
		p1.isMale = true;
		System.out.println(p1.name);
		
		//调用方法:"对象.方法"
		p1.eat();
		p1.sleep();
		p1.talk("Chinese");
		
		//**************************
		Person p2 = new Person();
		System.out.println(p2.name);
		System.out.println(p2.isMale);
		
		//**************************
    	//将p1变量保存的对象地址赋值给p3,导致p1和p3指向了堆空间中的同一个对象实体。
        //类似array
		Person p3 = p1;
		System.out.println(p3.name);//Tom
		
		p3.age = 99;
		System.out.println(p1.age);//10
		
		//创建类
		Tiger t1 = new Tiger();
		
		//调用属性
		System.out.println(t1.name);
		t1.name = "Queen";
		System.out.println(t1.name);
		t1.age = 8;
		
		//调用方法
		t1.eat();
		t1.state();
		
	}
}
//1.创建类:设计类的成员
class Person{
	//属性
	String name;
	int age = 1;
	boolean isMale;
	
	//方法
	public void eat(){
		System.out.println("人可以吃饭");
	}
	
	public void sleep(){
		System.out.println("人可以睡觉");
	}
	
	public void talk(String language){
		System.out.println("人可以说话,使用的是:" + language);
	}
}

class Tiger{
	//属性
	String name = "King";
	int age = 10;
	boolean isMale;
	
	//方法
	public void eat(){
		System.out.println("老虎啥都吃");
	}
	
	public void state() {
		System.out.println("老虎是丛林之王!");
	}
}

1.4 内存解析

1.5 类中方法的声明和使用

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


 * 比如:Math类:sqrt()\random() \...
 *     Scanner类:nextXxx() ...
 *     Arrays类:sort() \ binarySearch() \ toString() \ equals() \ ...
 * 
 * 1.举例:
 * public void eat(){}
 * public void sleep(int hour){}
 * public String getName(){}
 * public String getNation(String nation){}
 


 1.5.2 方法的声明

 

             权限修饰符public  返回值类型void  方法名sort(形参列表arr){
                    方法体
              }
 *   注意:static、final、abstract 来修饰的方法,后面再讲。
  


 1.5.3 说明


 *         3.1 关于权限修饰符:默认方法的权限修饰符先都使用public
 *             Java规定的4种权限修饰符:private、public、缺省、protected  -->封装性再细说
 * 
 *         3.2 返回值类型: 有返回值  vs 没有返回值
 *             3.2.1  如果方法有返回值,则必须在方法声明时,指定返回值的类型。同时,方法中,需要使用
 *                return关键字来返回指定类型的变量或常量:“return 数据”。
 *                   如果方法没有返回值,则方法声明时,使用void来表示。通常,没有返回值的方法中,就不需要
 *               使用return.但是,如果使用的话,只能“return;”表示结束此方法的意思。
 * 
 *             3.2.2 我们定义方法该不该有返回值?
 *                 ① 题目要求
 *                 ② 凭经验:具体问题具体分析
 * 
 *      3.3 方法名:属于标识符,遵循标识符的规则和规范,“见名知意”
 *      
 *      3.4 形参列表: 方法可以声明0个,1个,或多个形参。
 *         3.4.1 格式:数据类型1 形参1,数据类型2 形参2,...
 *         
 *         3.4.2 我们定义方法时,该不该定义形参?
 *                 ① 题目要求
 *                 ② 凭经验:具体问题具体分析
 *      
 *      3.5 方法体:方法功能的体现。         
 
 

1.5.4 return关键字的使用:


 *      1.使用范围:使用在方法体中
 *      2.作用: ① 结束方法
 *              ② 针对于有返回值类型的方法,使用"return 数据"方法返回所要的数据。
 *      3.注意点:return关键字后面不可以声明执行语句。

 

 
1.5.5 方法的使用中:


 *      5.1可以调用当前类的属性或方法
 *      5.2特殊的:方法A中又调用了方法A:递归方法。
 *      5.3方法中,不可以定义方法。
 

 

public class CustomerTest {
	public static void main(String[] args) {
		Customer cust1 = new Customer();
		cust1.eat();
		//测试形参是否需要设置的问题
//		int[] arr = new int[]{3,4,5,1,2,34,1};
//		cust1.sort(arr);//排号后直接输出就ok
		cust1.sleep(8);
	}
}

//客户类
class Customer{
	//属性
	String name;
	int age;
	boolean isMale;
	
	//方法
	public void eat(){
		System.out.println("客户吃饭");
		return;//为什么要加?
	}
	
	public void sleep(int hour){
		System.out.println("休息了" + hour + "个小时");
		eat();//5.1
		//sleep(10);5.2递归调用,会爆炸
	}
	
	public String getName(){
		
		if(age > 18){//5.1
			return name;
			
		}else{
			return "Tom";
		}
	}
	
	public String getNation(String nation){
		String info = "我的国籍是 " + nation;
		return info;
	}
	
	//体会形参是否需要设置的问题
//	public void sort(int[] arr){//排完就好
//		
//	}
//	public void sort(){
//		int[] arr = new int[]{3,4,5,2,5,63,2,5};
//		//。。。。
//	}
	
	//不能在方法中调用方法
	public void info(){
		//错误的
//		public void swim(){
//			
//		}
}

 

1.5 课后练习

1.5.1 写一个类并调用

写一个Person类

package com.exam.oop;

public class Person {
	String name;
	int age;//默认值0
	/*
	 * 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;
	}
}

 

调用Person类

package com.exam.oop;
/*
 * 要求:
 * (1)创建Person类的对象,设置该对象的name、age和sex属性,调用study方法,
 * 输出字符串“studying”,调用showAge()方法显示age值,
 * 调用addAge()方法给对象的age属性值增加2岁。
 * (2)创建第二个对象,执行上述操作,体会同一个类的不同对象之间的关系。
 * 
 * 
 */
public class PersonTest {
	public static void main(String[] args) {
		Person p1 = new Person();
		
		p1.name = "Tom";
		p1.age = 18;
		p1.sex = 1;
		
		p1.study();
		
		p1.showAge();
		
		int newAge = p1.addAge(2);
		System.out.println(p1.name + " 的新年龄为: " + newAge);
		System.out.println(p1.age);
		
		//**************************
		Person p2 = new Person();
		p2.showAge();
		p2.addAge(10);
		p2.showAge();
		
		p1.showAge();
		
	}
}

1.5.2 编写一个可以输出矩阵的方法

package com.exam.oop;

public class Exam3Test {
	public static void main(String[] args) {
		Exam3Test e1 = new Exam3Test();
		int area = e1.method(10, 8);
		System.out.println("area is " + area);
	}
	
	public int method(int m, int n){
		//m为行参数 n为列参数
        //m n为形式参数,做菜的时候需要原材料了!
		for (int i = 0; i < m; i++) {
			for (int j = 0; j < n; j++) {
				System.out.print("* ");
			}
			System.out.println("\n");
		}
		return m * n;
	}
}

1.5.3 编写一个students类

方法一:单独写了两个流程,没有封装

package com.exam.oop;

public class StudentTest {
	public static void main(String[] args) {
		//声明一个Student类型的数组
		int personNum = 20;
		Student[] stus = new Student[personNum];
		//String[] str = new String[] 对象数组
		
		for (int i = 0; i < personNum ; i++) {
			//给元素赋值
			stus[i] = new Student();
			//给student对象的属性赋值
			stus[i].number = i + 1;
			stus[i].state = (int)(Math.round(Math.random() * 3));
			stus[i].score = (int)(Math.random() * 101);


			
		}
		//遍历学生数组
		//映射关系:栈stus的地址——》堆stus[i]的地址——》stus[i]的属性值
		//打印每个对象的地址值
		for (int j = 0; j < stus.length; j++) {
			if (stus[j].state == 3) {
				System.out.println(stus[j].info());
			}	
		}
		
		//冒泡排序:从小到大
		for (int i = 0; i < stus.length - 1; i++) {
			for (int j = 0; j < stus.length - 1 - i; j++) {
				if (stus[j].score > stus[j + 1].score) {
					int temp = stus[j].score;
					stus[j].score = stus[j + 1].score;
					stus[j + 1].score = temp;
				}
			}
		}
		for (int i = 0; i < stus.length; i++) {
			System.out.println(stus[i].info());
		}
	}
}

class Student{
	int number;//学号
	int state;//年级
	int score;//成绩
	
	//显示学生信息的方法
	public String info(){
		return "学号:" + number + ", 年级:" + state + ", 成绩:" + score;
	}
}

只要有new就会在堆里面生成一个

方法二:将一些操作封装起来 

package com.exam.oop;

public class StudentTest3 {
	public static void main(String[] args) {
		//声明一个Student类型的数组
		int personNum = 20;
		
		//利用Student1类声明一个元素为Student1的数组
		Student1[] stus = new Student1[personNum];
		//String[] str = new String[] 对象数组
		
		//给stus赋值
		for (int i = 0; i < personNum ; i++) {
			//给元素赋值
			stus[i] = new Student1();
			//给student对象的属性赋值
			stus[i].number = i + 1;
			stus[i].state = (int)(Math.round(Math.random() * 3));
			stus[i].score = (int)(Math.random() * 101);		
		}
		
		//生成主类的对象 test
		StudentTest3 test = new StudentTest3();
		
		//test调用主类的方法
		//遍历学生数组
		test.print(stus);
		test.searchState(stus, 3);
		test.sort(stus);

	}

		


		
		
	//遍历Student1[]数组的操作
	public void print(Student1[] stus){
		System.out.println("遍历学生数组:");
		for (int i = 0; i < stus.length; i++) {
			System.out.println(stus[i].info());
		}
	}
		
	//查找Student1[]数组中指定年级的元素
	public void searchState(Student1[] stus,int state){
		System.out.println("遍历学生数组中年级为 " + state + " 的学生");
		for (int j = 0; j < stus.length; j++) {
			if (stus[j].state == state) {
				System.out.println(stus[j].info());
			}	
		}
	}
	
	
	public void sort(Student1[] stus){
		//冒泡排序:从小到大
		System.out.println("对数组进行冒泡排序:");
		for (int i = 0; i < stus.length - 1; i++) {
			for (int j = 0; j < stus.length - 1 - i; j++) {
				if (stus[j].score > stus[j + 1].score) {
					int temp = stus[j].score;
					stus[j].score = stus[j + 1].score;
					stus[j + 1].score = temp;
				}
			}
		}
		for (int i = 0; i < stus.length; i++) {
			//System.out.println(stus[i]);//输出地址
			System.out.println(stus[i].info());
		}
	}
}

class Student1{
	int number;//学号
	int state;//年级
	int score;//成绩
	
	//显示学生信息的方法
	public String info(){
		return "学号:" + number + ", 年级:" + state + ", 成绩:" + score;
	}
}

重构:方法都放到子类,主类尽量简洁

package com.exam.oop;

public class StudentTest3 {
	public static void main(String[] args) {
		//声明一个Student类型的数组
		int personNum = 20;
		
		//利用Student1类声明一个元素为Student1的数组
		Student1[] stus = new Student1[personNum];
		//什么类型的数组?         生成一下?
		//String[] str = new String[] 对象数组
		
		//给stus赋值
		for (int i = 0; i < personNum ; i++) {
			//给元素赋值
			stus[i] = new Student1();
			//给student对象的属性赋值
			stus[i].number = i + 1;
			stus[i].state = (int)(Math.round(Math.random() * 6));
			stus[i].score = (int)(Math.random() * 101);		
		}
		
		//生成主类的对象 test
		StudentTest test = new StudentTest();
		
		//test调用主类的方法
		//遍历学生数组
		test.print(stus);
		test.searchState(stus, 4);
		test.sort(stus);

	}	
}

class Student1{
	int number;//学号
	int state;//年级
	int score;//成绩
	
	//显示学生信息的方法
	public String info(){
		return "学号:" + number + ", 年级:" + state + ", 成绩:" + score;
	}
}

class StudentTest{
	//遍历Student1[]数组的操作
	public void print(Student1[] stus){
		System.out.println("遍历学生数组:");
		for (int i = 0; i < stus.length; i++) {
			System.out.println(stus[i].info());
		}
	}
		
	//查找Student1[]数组中指定年级的元素
	public void searchState(Student1[] stus,int state){
		System.out.println("遍历学生数组中年级为 " + state + " 的学生");
		for (int j = 0; j < stus.length; j++) {
			if (stus[j].state == state) {
				System.out.println(stus[j].info());
			}	
		}
	}
	
	
	public void sort(Student1[] stus){
		//冒泡排序:从小到大
		System.out.println("对数组进行冒泡排序:");
		for (int i = 0; i < stus.length - 1; i++) {
			for (int j = 0; j < stus.length - 1 - i; j++) {
				if (stus[j].score > stus[j + 1].score) {
					int temp = stus[j].score;
					stus[j].score = stus[j + 1].score;
					stus[j + 1].score = temp;
				}
			}
		}
		for (int i = 0; i < stus.length; i++) {
			//System.out.println(stus[i]);//输出地址
			System.out.println(stus[i].info());
		}
	}
}

1.5.4 MyDate类

1.6 Day8测试

1.6.1 面向对象思想编程内容的三条主线分别是什么?

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

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

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

 

1.6.2 谈谈你对面向对象中类和对象的理解,并指出二者的关系?

类:抽象

对象:符合抽象出来的属性,被定义出来的一个实实在在的个体

 

1.6.3 面向对象思想的体现一:类和对象的创建和执行操作有哪三步?

创建类:class xxx{}

类的实例化:xxx yyy = new xxx()       xxx[] yyy = new xxx[]

调用类的方法、属性:xxx.ccc = ?  xxx.bbb()

 

1.6.4类的方法内是否可以定义变量?是否可以调用属性?是否可以定义方法?是否可以调用方法?

y y n y

package playground;

public class TigerTest {
	public static void main(String[] args) {
		Tiger t1 = new Tiger();
		
		t1.name = "xiaolong";
		t1.age = 19;
		t1.showAge();//显示虚岁,实岁不变

		t1.minusAge(10);//2.该方法会调用age属性 age=0
//		t1.showAge();
		
	}
}

class Tiger {
	String name;
	int age;
	boolean sex;
	
	public void bite(){
		System.out.println("老虎可以咬人!");
	}
	
	//展示当前性别
	public void showSex(boolean sex){
		if (sex) {
			System.out.println("是雄性老虎!");
		} else {
			System.out.println("是雌性老虎!");
		}
	}
	
	//展示年龄
	public void showAge(){
		//1.声明变量
		int addAge = 3;
		System.out.println("这只老虎的年龄是(虚岁):" + (age + addAge));
		//4.调用类中的其他方法
		bite();
		showSex(true);
	}
	
	//减少年龄
	public int minusAge(int j){
		//2.调用age
		age -= j;
		System.out.println("老虎现在的年龄是:" + age);
		return age;
	}
}

2 面向对象上概念总结

2.1 类与对象

2.1.1 JVM内存结构

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

《JVM规范》

虚拟机栈:将局部变量存储在栈结构中。

堆:我们将new出来的结构(数组、对象)加载到堆空间中。补充:对象的属性(非 state)加载到堆空间中。方法区:类的加载信息、常量池、静态域。

2.2 类的结构之一:属性

/*
 * 类中属性的使用
 * 
 * 属性(成员变量)   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  (或'\u0000')
 *             布尔型(boolean):false
 * 
 *             引用数据类型(类、数组、接口):null
 * 
 *         局部变量:没有默认初始化值。
 *          意味着,我们在调用局部变量之前,一定要显式赋值。
 *             特别地:形参在调用时,我们赋值即可。
 * 
 *         2.4 在内存中加载的位置:
 *         属性:加载到堆空间中   (非static)
 *         局部变量:加载到栈空间
 * 
 */

2.2.1 变量的分类方法

2.3 类的结构之一:方法

/*
 * 类中方法的声明和使用
 * 
 * 方法:描述类应该具有的功能。
 * 
 * 比如:Math类:sqrt()\random() \...
 *     Scanner类:nextXxx() ...
 *     Arrays类:sort() \ binarySearch() \ toString() \ equals() \ ...
 * 
 * 1.举例:
 * public void eat(){}
 * public void sleep(int hour){}
 * public String getName(){}
 * public String getNation(String nation){}
 * 
 * 2. 方法的声明:权限修饰符  返回值类型  方法名(形参列表){
 *                     方法体
 *               }

 *   注意:static、final、abstract 来修饰的方法,后面再讲。
 *   
 * 3. 说明:
 *         3.1 关于权限修饰符:默认方法的权限修饰符先都使用public
 *             Java规定的4种权限修饰符:private、public、缺省、protected  -->封装性再细说
 * 
 *         3.2 返回值类型: 有返回值  vs 没有返回值
 *             3.2.1  如果方法有返回值,则必须在方法声明时,指定返回值的类型。同时,方法中,需要使用
 *                return关键字来返回指定类型的变量或常量:“return 数据”。
 *                   如果方法没有返回值,则方法声明时,使用void来表示。通常,没有返回值的方法中,就不需要
 *               使用return.但是,如果使用的话,只能“return;”表示结束此方法的意思。
 * 
 *             3.2.2 我们定义方法该不该有返回值?
 *                 ① 题目要求
 *                 ② 凭经验:具体问题具体分析
 * 
 *      3.3 方法名:属于标识符,遵循标识符的规则和规范,“见名知意”
 *      
 *      3.4 形参列表: 方法可以声明0个,1个,或多个形参。
 *         3.4.1 格式:数据类型1 形参1,数据类型2 形参2,...
 *         
 *         3.4.2 我们定义方法时,该不该定义形参?
 *                 ① 题目要求
 *                 ② 凭经验:具体问题具体分析
 *      
 *      3.5 方法体:方法功能的体现。         
 


 2.3.1.return关键字


 *      1.使用范围:使用在方法体中
 *      2.作用: ① 结束方法
 *              ② 针对于有返回值类型的方法,使用"return 数据"方法返回所要的数据。
 *      3.注意点:return关键字后面不可以声明执行语句。
 


 *  5. 方法的使用中:
 *      5.1可以调用当前类的属性或方法
 *      5.2特殊的:方法A中又调用了方法A:递归方法。
 *         5.3方法中,不可以定义方法。
 */

3 匿名对象

代码

内存解析

在堆里面生成,赋值给show方法,形参作为局部变量储存在栈中。即将new出来的部分的地址值赋值给形参。

/**
 * 
 */
package com.lee.java;

/**
 * @Description
 * @author LF E-mail:ljjrichard@163.com
 * @version
 * @date 2021年5月26日上午9:51:11
 */
public class Instance {
	public static void main(String[] args) {
		Phone p = new Phone();
		System.out.println(p);//com.lee.java.Phone@15db9742
		
//		p.sendEmail();
//		p.playGame();
		
		//匿名对象
		new Phone().sendEmail();
		new Phone().playGame();
		new Phone().price = 1999;
		new Phone().showPrice();//0.0
		
		//*************************************
		PhoneMall mall = new PhoneMall();
		//匿名对象
		mall.show(new Phone());
		
	}
}

class PhoneMall{
	public void show(Phone phone){
		phone.sendEmail();
		phone.playGame();
	}
}

class Phone{
	double price;//价格
	
	public void sendEmail(){
		System.out.println("发送邮件");
	}
	
	public void playGame(){
		System.out.println("玩游戏");
	}
	
	public void showPrice(){
		System.out.println("手机价格为:" + price);
	}
}

4 自己写一个数组类

/**
 * 
 */
package com.lee.java;

/**
 * @Description
 * @author LF E-mail:ljjrichard@163.com
 * @version
 * @date 2021年5月26日上午10:14:58
 */
/**
 * 自定义数组的工具类
 * 
 */
public class ArrayTools {
	//求数组的最大值
	public int getMax(int[] arr) {
		int maxValue = arr[0];
		for (int i = 0; i < arr.length; i++) {
			if (arr[i] > maxValue) {
				maxValue = arr[i];
			}
		}
		return maxValue;
	}
	
	//求数组最小值
	public int getMin(int[] arr) {
		int minValue = arr[0];
		for (int i = 0; i < arr.length; i++) {
			if (arr[i] < minValue) {
				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 int getAvg(int[] arr){
		return getSum(arr) / arr.length;
	}
	
	//反转数组
	public void reverse(int[] arr) {
		for (int i = 0; i < arr.length / 2; i++) {
			int temp = arr[i];
			arr[i] = arr[arr.length - 1 - i];
			arr[arr.length - 1 - i] = temp;		
		}
	}
	
	//复制数组
	public int[] copy(int[] arr) {
		int[] arr1 = new int[arr.length];
		for (int i = 0; i < arr1.length; i++) {
			arr1[i] = arr[i];
		}
		return arr1;
	} 
	
	//数组排序
	public void sort(int[] arr){
		//冒泡排序 从小到大
		for (int i = 0; i < arr.length - 1; i++) {
			for (int j = 0; j < arr.length  - 1 - i; j++) {
				if (arr[j] > arr[j + 1]) {
					swap(arr,j,j + 1);
				}
			}
		}
	}
	
	//交换数组两个位置的元素
	public void swap(int[] arr, int i, int j) {
		int temp = arr[i];
		arr[i] = arr[j];
		arr[j] = temp;
	}
	
	//遍历数组
	public void print(int[] arr) {
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + "\t");
		}
		System.out.println();
	}
	
	//查找指定元素
	public int getIndex(int[] arr, int dest) {
		//线性查找
		for (int i = 0; i < arr.length; i++) {
			if (dest == arr[i]) {
				return i;
			}
		}
		return -1;
	}
}
/**
 * 
 */
package com.lee.java;

/**
 * @Description
 * @author LF E-mail:ljjrichard@163.com
 * @version
 * @date 2021年5月26日上午10:34:06
 */
public class ArrayToolsTest {
public static void main(String[] args) {
	ArrayTools util = new ArrayTools();
	int[] arr = new int[]{32,34,32,5,3,54,654,-98,0,-53,5};
	int max = util.getMax(arr);
	System.out.println("最大值为:" + max);
	
	System.out.println("排序前:");
	util.print(arr);
	
	
	
	util.sort(arr);
	System.out.println("排序后:");
	util.print(arr);
	
	int key = -33;
	System.out.println("查找:" + key);
	int index = util.getIndex(arr, key);
	if(index >= 0){
		System.out.println("找到了,索引地址为:" + index);
	}else{
		System.out.println("未找到");
	}
	
	System.out.println("反转前: ");
	util.print(arr);
	util.reverse(arr);
	System.out.println("反转后:");
	util.print(arr);
}
}

5 再谈方法

5.1 重载

/*
 * 方法的重载(overload)  loading...
 * 
 * 1.定义:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
 *     
 *  "两同一不同":同一个类相同方法名
 *            参数列表不同:参数个数不同,参数类型不同
 * 
 * 2. 举例:
 *    Arrays类中重载的sort() / binarySearch() 查API
 * 
 * 3.判断是否是重载:
 *    跟方法的权限修饰符、返回值类型、形参变量名、方法体都没有关系!
 *    
 * 4. 在通过对象调用方法时,如何确定某一个指定的方法:
 *      方法名 ---> 参数列表
 */

 

/**
 * 
 */
package com.lee.java1;

/**
 * @Description
 * @author LF E-mail:ljjrichard@163.com
 * @version
 * @date 2021年5月26日上午11:08:32
 */
public class OverLoadTest {
	public static void main(String[] args) {
		OverLoadTest test = new OverLoadTest();
		test.getSum(1, 2);//调用第一个/注释第一个会执行2
		test.getSum(1.0, 2.0);
		test.getSum("Nihao", 2);
	}
	
	//如下四个方法构成了重载
	public void getSum(int i, int j){
		System.out.println("1");
	}
	
	public void getSum(double i, double j){
		System.out.println("2");
	}
	
	public void getSum(String s, int i){
		System.out.println("3");
	}
	
	public void getSum(int i, String s){
		System.out.println("4");
	}
	
	//如下的3个方法不能与上述4个方法构成重载
//	public int getSum(int i,int j){
//		return 0;
//	}
	
//	public void getSum(int m,int n){
//		
//	}
	
//	private void getSum(int i,int j){
//		
//	}
}

5.2 可变个数的形参

/*
 * 可变个数形参的方法
 * 
 * 1.jdk 5.0新增的内容
 * 2.具体使用:
 *   2.1 可变个数形参的格式:数据类型 ... 变量名
 *   2.2 当调用可变个数形参的方法时,传入的参数个数可以是:0个,1个,2个,。。。
 *   2.3 可变个数形参的方法与本类中方法名相同,形参不同的方法之间构成重载
 *   2.4 可变个数形参的方法与本类中方法名相同,形参类型也相同的数组之间不构成重载。换句话说,二者不能共存。
 *   2.5 可变个数形参在方法的形参中,必须声明在末尾
 *      2.6  可变个数形参在方法的形参中,最多只能声明一个可变形参。
 * 
 */

/**
 * 
 */
package com.lee.java1;

/**
 * @Description
 * @author LF E-mail:ljjrichard@163.com
 * @version
 * @date 2021年5月26日上午11:31:59
 */
public class MethodArgsTest {
	public static void main(String[] args) {
		MethodArgsTest test = new MethodArgsTest();
		test.show(12);
		test.show("hello");
		test.show("hello","world","yeah");
		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){
//		
//	}
}

5.3 方法参数的值传递机制

/*
 * 
 * 关于变量的赋值:
 * 
 *  如果变量是基本数据类型,此时赋值的是变量所保存的数据值。

 */

/**
 * 
 */
package com.lee.java1;

/**
 * @Description
 * @author LF E-mail:ljjrichard@163.com
 * @version
 * @date 2021年5月26日下午3:14:28
 */
/**
 * 方法的形参的传递机制:值传递
 * 
 * 1.形参:方法定义时,声明的小括号内的参数
 *   实参:方法调用时,实际传递给形参的数据
 * 
 * 2.值传递机制:
 * 如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值。
 * 如果参数是引用数据类型,此时实参赋给形参的是实参存储数据的地址值。
 * 
 */
public class ValueTransferTest1 {
	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;
		ValueTransferTest1 test = new ValueTransferTest1();
		test.swap(m, n);
		
		System.out.println("m = " + m + ", n = " + n);
		
		
	}
	//形式参数。此方法没法改变两个数
	public void swap(int m,int n){
		int temp = m ;
		m = n;
		n = temp;
	}
}

第二种方法: *  如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值。

 

string是类 特例

5.3.1 面试题 参数传递

15 0 

20

/**
 * 
 */
package com.lee.java1;

/**
 * @Description
 * @author LF E-mail:ljjrichard@163.com
 * @version
 * @date 2021年5月27日上午9:29:34
 */
public class ValueTransferTest3 {
	public static void main(String[] args) {
		ValueTransferTest3  test = new ValueTransferTest3();//栈空间压入test,test指向堆空间
		test.first();
	}
	
	public void first() {
		int i = 5;
		Value v = new Value();
		v.i = 25;
		second(v, i);
		System.out.println(v.i);
	}
	
	public void second(Value v, int i) {
		i = 0;
		v.i = 20;
		Value val = new Value();
		v = val;
		System.out.println(v.i + " " + i);
	}
}

class Value {
	int i = 15;
}

5.3.2 面试题 貌似考参数传递

/**
 * 
 */
package com.lee.java1;

import java.io.PrintStream;

/**
 * @Description
 * @author LF E-mail:ljjrichard@163.com
 * @version
 * @date 2021年5月27日上午9:43:42
 */
public class Test1 {
	public static void main(String[] args) {
		int a = 10;
		int b = 10;
		method(a,b);
		System.out.println("a = " + a);
		System.out.println("b = " + b);
		//仅打印a=100 b=200
	}
	
	//加了static就不用声明对象也可以调用方法
//	public static void method(int a, int b){
//		a *= 10;
//		b *= 20;
//		System.out.println(a);
//		System.out.println(b);
//		System.exit(0);
//	}
	
	public static void method(int a, int b){
		PrintStream ps = new PrintStream(System.out){
			
			public void println(String x){
				if ("a = 10".equals(x)) {
					x = "a = 100";
				}else if("b = 10".equals(x)) {
					x = "b = 200";
				}
				super.println(x);
			}
		};
		System.setOut(ps);

	}
}


5.3.3 看似简单实则有坑的题

/**
 * 
 */
package com.lee.java1;

/**
 * @Description
 * @author LF E-mail:ljjrichard@163.com
 * @version
 * @date 2021年5月27日上午10:42:05
 */
//让数组的每个位置的元素除以首位置的元素,得到结果,作为该位置的新值
public class Test2 {
	public static void main(String[] args) {
		int[] arr = new int[]{12,3,3,34,56,77,432};
		for (int i = arr.length - 1; i >= 0; i--) {
			arr[i] = arr[i] / arr[0];
		}
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + " ");
		}
	}
}

 

/**
 * 
 */
package com.lee.java1;

/**
 * @Description
 * @author LF E-mail:ljjrichard@163.com
 * @version
 * @date 2021年5月27日上午10:48:46
 */
public class ArrayPrintTest {
	public static void main(String[] args) {
		int[] arr = new int[]{1,2,3};
		System.out.println(arr);//地址值
		
		char[] arr1 = new char[]{'a','b'};
		System.out.println(arr1);//ab
	}
}

5.3.4 将对象作为参数传递给方法

/**
 * 
 */
package com.lee.java1;

/**
 * @Description
 * @author LF E-mail:ljjrichard@163.com
 * @version
 * @date 2021年5月27日上午11:10:04
 */
public class CircleTest {
	public static void main(String[] args) {
		Circle c1 = new Circle();
		PassObject p1 = new PassObject();
		p1.printAreas(c1, 7);
		System.out.println("now radius is " + c1.radius);
	}	
}

class Circle{
	double radius;
	public double findArea(){
		return Math.PI * radius * radius;
	}
}

class PassObject{
	public void printAreas(Circle c, int time){
		
		System.out.println("Radius\t\tArea");
		for (int i = 1; i <= time; i++) {
			c.radius = i;
			System.out.println(i + "\t\t" + c.findArea());
		}
		c.radius = time + 1;
		
	}
}

5.4 递归


 * 递归方法的使用(了解)
 * 1.递归方法:一个方法体内调用它自身。
 * 2. 方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制。
 * 递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环。

 

n级台阶,我只能走1级或者2级,一共有几种走法

 

6 方法的课后练习

6.1 什么是方法的重载?

“两同一不同”:同一个类、相同方法名;参数列表不同。

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

6.2 说明Java方法中的参数传递机制的具体体现?

基本数据类型:数据值

引用数据类型:地址值 (含变量的数据类型)

Person p1 =  new Person();  eat();age

User u1 = p1;//编译错误    (逆向思维、反证法)

u1.eat()  u1.age

3. 成员变量和局部变量在声明的位置上、是否有默认初始化值上、是否能有权限修饰符修饰上、内存分配的位置上有何不同?

6.4. 谈谈return关键字的使用

① 结束方法  ② 针对于有返回值的方法,return + 返回数据

5. 提供如下代码的内存解析

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

2. 变量:成员变量  vs 局部变量(方法内、方法形参、构造器内、构造器形参、代码块内)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
门禁系统是一个很好的面向对象的应用场景。在Java中,我们可以定义一个门禁系统,该包含门禁系统的属性和方法。门禁系统可以包括以下属性: - 门禁卡号:每个门禁卡有唯一的卡号,用于识别持卡人身份。 - 持卡人姓名:每个门禁卡都有持卡人的姓名,用于显示在门禁系统上。 - 进入时间:记录持卡人进入门禁系统的时间,用于计算停留时间。 门禁系统可以包括以下方法: - 打卡:持卡人将门禁卡放在门禁系统上进行打卡操作,系统会记录打卡时间,并且显示持卡人的姓名。 - 查询:持卡人可以查询自己的进出记录和停留时间。 - 统计:系统可以统计每个持卡人的停留时间,并且按照时间长短进行排名。 下面是一个简单的门禁系统的实现: ``` public class AccessControlSystem { private String cardId; private String cardHolderName; private Date enterTime; private Date exitTime; // 打卡 public void punchCard(String cardId, String cardHolderName) { this.cardId = cardId; this.cardHolderName = cardHolderName; this.enterTime = new Date(); System.out.println("持卡人:" + cardHolderName + " 进入门禁系统,时间:" + enterTime); } // 查询 public void queryRecord() { System.out.println("持卡人:" + cardHolderName + " 进出记录:"); System.out.println("进入时间:" + enterTime); System.out.println("离开时间:" + exitTime); System.out.println("停留时间:" + (exitTime.getTime() - enterTime.getTime()) / 1000 + "秒"); } // 统计 public void ranking(List<AccessControlSystem> accessControlSystems) { Collections.sort(accessControlSystems, Comparator.comparingLong(a -> a.exitTime.getTime() - a.enterTime.getTime())); System.out.println("停留时间排名:"); for (int i = 0; i < accessControlSystems.size(); i++) { AccessControlSystem accessControlSystem = accessControlSystems.get(i); System.out.println("第" + (i + 1) + "名:" + accessControlSystem.cardHolderName + ",停留时间:" + (accessControlSystem.exitTime.getTime() - accessControlSystem.enterTime.getTime()) / 1000 + "秒"); } } // 离开 public void leave() { this.exitTime = new Date(); System.out.println("持卡人:" + cardHolderName + " 离开门禁系统,时间:" + exitTime); } } ``` 在上面的实现中,我们定义了一个AccessControlSystem,并且包含了打卡、查询、统计、离开等方法。其中,打卡方法会记录持卡人进入门禁系统的时间,查询方法会显示持卡人的进出记录和停留时间,统计方法会按照停留时间长短进行排名,离开方法会记录持卡人离开门禁系统的时间。 我们可以在主函数中创建一个AccessControlSystem对象,并且模拟持卡人的进出操作: ``` public static void main(String[] args) { AccessControlSystem accessControlSystem = new AccessControlSystem(); accessControlSystem.punchCard("001", "张三"); accessControlSystem.leave(); accessControlSystem.queryRecord(); AccessControlSystem accessControlSystem2 = new AccessControlSystem(); accessControlSystem2.punchCard("002", "李四"); accessControlSystem2.leave(); accessControlSystem2.queryRecord(); List<AccessControlSystem> accessControlSystems = new ArrayList<>(); accessControlSystems.add(accessControlSystem); accessControlSystems.add(accessControlSystem2); accessControlSystem.ranking(accessControlSystems); } ``` 上面的代码会创建两个持卡人张三和李四,分别进行打卡和离开操作,并且进行查询和统计操作。每次操作都会通过AccessControlSystem的方法进行处理,并且输出对应的结果。 这样,我们就实现了一个简单的门禁系统,并且通过面向对象的方式进行了设计和实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值