学习面向对象内容的三条主线:
Java类及类的成员:属性,方法,构造器(前三个是重点);代码块,内部类
面向对象的特征:封装,继承,多态,(抽象)(如果除三个之外还要补充一个就还有抽象)
其他关键字的使用: this,super,package,import,static,final,interface,abstact等
1.面向对象编程概述(了解):
1.1程序设计的思路:
面向对象,是软件开发中的一种编程风格,除了面向对象,还有面向过程,指令式编程和函数式编程。
1.面向过程的程序设计思想,简称pop
关注的焦点是过程:过程就是操作数据的步骤,如果某个过程的实现代码反复出现,那么就可以把这个过程抽取为一个函数,这样就可以简化代码。
代表:C语言
是一种执行者思维,适合解决简单问题,扩展能力差,后期维护难度大
2.面向对象的程序设计思想,简称OOP
关注的焦点是类:在计算机程序设计过程中,参照现实中事物,将事物的属性特征,行为特征抽象出来,用类来表示
代表:Java,c#, C++等
代码结构:以类为组织,每种事物都具备自己的属性和行为/功能
是一种设计者思维,适合解决复杂问题,代码扩展性强,可维护性高
千万不要把面向对象和面向过程对立,他俩是相辅相成的
2.Java语言的基本元素:类和对象
类和对象概述:
类:具有相同特征的事物的抽象描述,是抽象的,概念上的定义
对象:实际存在的该类事物的每个个体,是具体的,因而也称为实例
可以理解为:类==>抽象概念上的人。对象==>实实在在的某个人
类的成员的概述:
面向对象程序设计的重点是“类的设计”,类的设计就是类的成员的设计
现实世界的生物体都是由最基本的细胞构成的,同理,Java代码世界是由诸多不同功能的类构成的
现实生物世界中的细胞是由细胞核,细胞质等构成。Java中的用类class来描述事物也是如此
类,是一组相关属性和行为的集合,这也是类最基本的两个成员
属性:该类事物的状态信息,对应类中的成员变量
成员变量<==>属性<==>Field
行为:该类事物要做什么操作,或者是基于事物的状态能做什么。对应类中的成员方法
(成员)方法<==>函数<==>Method
类的定义:
定义一个Phone类:
//类的定义
public class Phone {
//属性(就是变量)
String brand;//品牌
double price;//价格
//方法(能做的行为)
public void call(){
System.out.println("手机能打电话");
}
public void sendMessage(String message){
System.out.println("发送信息 " + message);
}
public void playGame(){
System.out.println("手机可以玩游戏");
}
}
调用这个类:
public class PhoneTest {//Phone类的测试
public static void main(String[] args) {
//创建phone的对象
Phone p1 = new Phone();
//通过phone的对象,调用其内部的属性
p1.brand = "huawei";
p1.price = 3999;
//调用方法
p1.call();
p1.sendMessage("有内鬼终止交易");
p1.playGame();
}
}
类的实例化(创建类的对象):
格式:类的类型 对象名 = new 创建的实体()
举例:
Phone p1 = new Phone();
Scanner scan = new Scanner(System.in);
面向对象完成具体功能的操作的三步流程:
步骤1:创建类,并设计这个类的内部成员(属性,方法)
方法2:创建类的对象,比如:Phone p1 = new Phone();
方法3:通过这个对象,调用其内部声明的属性或方法,完成相关的功能
练习:
创建的类:
public class Person {
//属性
String name;
int age;
char gender;
int high;
//方法
public void eat(){
System.out.println("吃饭");
}
public void sleep(int hour){
System.out.println("人至少保证每天" + hour + "个小时的睡眠");
}
public void habbit(String habbit){
System.out.println("我的爱好是 " + habbit);
}
}
创建的对象:
public class PersonTest {
public static void main(String[] args) {
//创建一个对象
Person per = new Person();
//通过对象,调用属性
per.name = "妄汐霜";
per.age = 19;
per.gender = '男';
//调用行为
per.eat();
per.habbit("学习,阅读,当纯小子");
per.sleep(15);
System.out.println(per.name);
System.out.println(per.gender);
System.out.println(per.age);
//再创建Person类的另一个对象
Person per2 = new Person();
//调用属性
per2.name = "夏攸";
per2.age = 21;
per2.gender = '女';
per2.high = 179;
//调用方法(属性)
per2.eat();
per2.sleep(16);
per2.habbit("打电动");
System.out.println(per2.name);
System.out.println(per2.age);
}
}
对象在内存中的分配涉及到的内存结构:
栈(stack):方法内定义的变量(比如上面例子里main方法中的per,per2)
堆(heap):new 出来的结构(数组的实体,对象的实体),包括对象中的属性
方法区(method area):存放类的模板。比如:上面例子中的Person类的模板(即整个Person这个类)
类中对象的内存解析:
创建类的一个对象:

创建类的多个对象:


强调:
Person p1 = new Person();
Person p2 = new Person();
创建了两个对象。
说明:创建类的多个对象时,每个对象在对空间中有一个对象实体,每个对象实体中保存着一分类的属性,如果修改某一个对象的某个属性值时,不会影响其他对象此属性的值
强调2:
Person p1 = new Person();
Person p3 = p1;
说明:此时p1,p3两个变量指向了堆空间中的同一个对象实体,如果通过其中某一个对象变量修改对象的属性时,会影响另一个对象,因为他俩是同一个。
再次强调面向对象完成具体功能的操作的三步流程(非常重要):
步骤1:创建类,并设计这个类的内部成员(属性,方法)
方法2:创建类的对象,比如:Phone p1 = new Phone();
方法3:通过这个对象,调用其内部声明的属性或方法,完成相关的功能
类的成员之一:属性(就是变量)
1.变量的分类:
角度一:按照数据类型来分:基本数据类型,引用数据类型(数组,类,接口,枚举,注解,记录)
角度二:按照变量在类中声明的位置不同:成员变量(或属性),局部变量(方法内,方法形参,构造器

2.属性的几个称谓:成员变量,属性,field(字段,域)
举例:
public class FileTest {
public static void main(String[] args) {
}
}
class Person1{
//属性(或成员变量)
String name;
int age;
char gender;
//上面的这些都是属性(或成员变量)
//方法
public void eat(){
String food = "宫保鸡丁";//这里的food就是局部变量
System.out.println("我喜欢吃" + food);
}
public void sleep(int hour){
System.out.println("一天要睡" + hour + "小时");
}
}
区分成员变量和局部变量:
相同点:
变量声明格式相同:数据类型 变量名 = 变量值;
只要是变量,都有其作用域。除了作用域就失效了
变量都必须先声明再使用。
不同点:
类中声明的位置不同: 属性:声明在类内,方法外的变量
局部变量:声明在方法内内部的变量
在内存中分配的位置不同: 属性:随着对象的创建,存储在堆空间中
局部变量:定义在方法之内的变量,存储在栈空间中
生命周期: 属性:随着对象的创建而创建,随着对象的消亡而消亡
局部变量:随着方法对应的栈帧入栈,局部变量会在栈中分配,随着方法对应的栈帧出栈,局部 变量消亡
作用域: 属性:在整个类的内部都是有效的
局部变量:仅限于声明此局部变量所在的方法中
是否可以有权限修饰符进行修饰: 权限修饰符(用于表示所修饰的结构可调用的范围的大小):public,protected,private,缺省
属性:是可以使用权限修饰符进行修饰
局部变量:不可以使用权限修饰符进行修饰
是否有默认值(重点):
属性:都有默认值
如果没有给属性进行显式赋值,就会赋默认值
局部变量:都没有默认值
注意:对于方法的形参而言,在调用方法时,给此形参赋值即可
练习:
创建的两个类:
public class Employee {
//定义属性
int id;//编号
String name;
int age;
int salary;
MyDate birthday;
}
public class MyDate {
int year;
int month;
int day;
}
应用这个类:
public class EmployeeTest {
public static void main(String[] args) {
//声明员工类Employee:包含属性:编号id。姓名name,年龄age,薪资:salary
//在main方法中创建两个对象,并为其属性赋值,并打印两个员工的信息
//创建两个对象
Employee emp1 = new Employee();
Employee emp2 = new Employee();
//为其属性赋值
emp1.id = 1;
emp2.id = 2;
emp1.name = "妄汐霜";
emp2.name = "夏攸";
emp1.age = 19;
emp2.age = 18;
emp1.salary = 10000;
emp2.salary = 7500;
//打印员工幸喜
System.out.println(emp1.id);
System.out.println(emp2.id);
System.out.println(emp1.name);
System.out.println(emp2.name);
System.out.println(emp1.age);
System.out.println(emp2.age);
System.out.println(emp1.salary);
System.out.println(emp2.salary);
//创建两个员工,并为他们的生日赋值
Employee emp3 = new Employee();
Employee emp4 = new Employee();
emp3.birthday = new MyDate();//这个不是基础数据类型,要和创建类的对象一样,通过new的方式新建
emp3.birthday.year = 2006;
emp3.birthday.month = 4;
emp3.birthday.day = 8;
//打印员工信息
System.out.println(emp3.birthday.year);
}
}
内存结构分析:

类的成员之二:方法(method)
1.使用方法的好处
方法是类或行为特征的抽象·,用来完成某个功能操作,在某些语言中也称为函数或过程
将功能封装为方法的目的是,可以实现代码复用,减少冗余,简化代码
Java里的方法不能独立存在,所有的方法必须声明在类里面
2.使用举例
Math.random()的random()方法
Math.sqrt(x)的sqrt(x)方法
Arrays类中的binarySearch()方法,sort()方法,equals()方法等等
3.声明举例
//方法
public void eat(){
System.out.println("人会吃饭");
}
public void sleep(int hour){
System.out.println("人每天至少睡" + hour + "小时");
}
public String interests(String habbit){
String info = "我的爱好是" + habbit;
return info;
}
public int getAge(){
return age;
}
4.方法声明的格式(重要):
权限修饰符 返回值类型 方法名(形参列表){
//方法体
}
5.具体的方法声明细节:
5.1权限修饰符:private / 缺省 / protected / public
5.2 返回值类型:描述当调用完此方法时,是否需要返回一个结果
分类:
无返回值类型:void
有具体的返回值类型:需要指明返回的数据的类型。可以是基本数据类型,也可以是引用 数据类型
需要配合return关键字;
5.3方法名:属于标识符,需要满足表示符命名的规定和规范,要见名知意
5.4 形参列表:形参,属于局部变量,且可以声明多个
格式:(形参类型1 形参1,形参类型2 形参2)
(如果有不确定的值要传进来,就用形参;没有的话,就不用。和C语言的函数差不多)
6.注意点:
Java所有的方法都不能独立存在,必须定义在类里。
必须先声明后使用。
Java中的方法不调用不执行,每调用一次,执行一次。
方法内可以调用本类中的方法或属性。
方法内不能定义方法。
7.return的使用:
7.1 return的作用
作用1:结束一个方法
作用2:结束一个方法的同时,可以返回数据给方法的调用者
注意点:return后面不能再声明语句
练习:
创建方法:
public class Employee {
//定义属性
int id;//编号
String name;
int age;
int salary;
MyDate birthday;
//定义方法,显示员工信息
public void show(){
System.out.println(" id = " + id + " name = " + name + " age = " + age + " salary = " + salary);
}
}
调用方法:
public class EmployeeTest {
public static void main(String[] args) {
//声明员工类Employee:包含属性:编号id。姓名name,年龄age,薪资:salary
//在main方法中创建两个对象,并为其属性赋值,并打印两个员工的信息
//创建两个对象
Employee emp1 = new Employee();
Employee emp2 = new Employee();
//为其属性赋值
emp1.id = 1;
emp2.id = 2;
emp1.name = "妄汐霜";
emp2.name = "夏攸";
emp1.age = 19;
emp2.age = 18;
emp1.salary = 10000;
emp2.salary = 7500;
//打印员工幸喜
System.out.println(emp1.id);
System.out.println(emp2.id);
System.out.println(emp1.name);
System.out.println(emp2.name);
System.out.println(emp1.age);
System.out.println(emp2.age);
System.out.println(emp1.salary);
System.out.println(emp2.salary);
//创建两个员工,并为他们的生日赋值
Employee emp3 = new Employee();
Employee emp4 = new Employee();
// emp3.birthday = new MyDate();//这个不是基础数据类型,要和创建类的对象一样,通过new的方式新建
// emp3.birthday.year = 2006;
// emp3.birthday.month = 4;
// emp3.birthday.day = 8;
// //打印员工信息
// System.out.println(emp3.birthday.year);
//不用再手打,调用show方法,直接打印。
emp1.show();
emp2.show();
}
}
8.方法调用的内存解析:
形参:方法在声明时,一对()内声明的一个或多个形式参数,简称为形参
实参:方法在被调用时,实际传递给形参的变量或常量,称为实际参数,简称实参

方法用完之后就会弹出栈
属性和方法的练习:
练习1:
创建的类:
public class Person3 {
//定义属性
String name;//姓名
int age;//年龄
char gender;//性别
// 定义方法,注意要定义在类里
public void study(){
System.out.println("studying");
}
public int showAge(){
return age;
}
public int addAge(int num){
age += num;
return age;
}
}
调用:
public class MethodExer2 {
public static void main(String[] args) {
//案例:创建Person类的对象,设置该对象的name,age和gender属性
//调用study方法,输出字符串“studying”
//调用showAge()方法,返回age值
//调用addAge(int addAge)方法给对象的age属性值增加addAge岁。
//创建属性,并给属性赋值
Person3 p1 = new Person3();
p1.name = "妄汐霜";
p1.age = 19;
p1.gender = '男';
//调用方法
p1.study();
System.out.println(p1.showAge());
System.out.println(p1.addAge(5));
}
}
练习2:
new对象的时候,要注意最前面和最后面的要和类名是一致的,而不是和对象所在的文件名一致
创建的类:
public class Method {
//声明方法
public void method1(int i,int j){
for( i = 1;i <= 10;i++){
for( j = 1;j <= 8;j++){
System.out.print("*");
}
System.out.println();
}
}
public int method2(int x,int y){
method1(x,y);
int area;
area = x*y;
return area;
}
public int method3(int m,int n){
for(int i = 1;i <= m;i++){
for(int j = 1;j <= n;j++){
System.out.print("*");
}
System.out.println();
}
return m*n;
}
}
创建对象并调用:
public class MethodExer3 {
public static void main(String[] args) {
//1.编写程序,声明一个method1方法,在方法中打印一个10*8的矩形,在main方法中调用此方法
//2。编写程序:声明一个method2方法,除打印一个10*8的矩形之外,再计算该矩形的面积,将其作为方法的结果返回,在main方法中调用此方法,并接受返回的面积
//3.编写程序,声明一个method3方法,再method3方法提供m和n两个参数,方法中打印一个m*n的矩形,并计算该矩形的面积,将其作为返回值返回,在main方法中调用该方法,接收返回的面积并打印
//先new一个类中的对象
Method obj = new Method();
//通过new的对象,调用方法
obj.method1(10,8);
System.out.println();
System.out.println(obj.method2(10, 8));
System.out.println();
System.out.println(obj.method3(5, 8));
}
}
练习3:
创建的类:
public class Circle {
//设计方法
public double Circle(int radius) {
double PI = 3.14;
double area = PI*radius * radius;
return area;
}
}
创建对象并调用:
public class MethodExer4 {
public static void main(String[] args) {
//利用Java,设计类Circle计算圆的面积
//先new一个对象
Circle c1 = new Circle();
//通过对象调用方法
System.out.println(c1.Circle(3));
}
}
练习4:
创建的类:
public class ArrayAndMethod {
/**
* 获取int[]数组的最大值
*
* @param arr 获取最大值的数组
* @return 数组的最大值
*/
public int max(int[] arr) {
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
/**
* 获取数组的最小值
*
* @param arr 要获取最小值的数组
* @return 数组的最小值
*/
public int min(int[] arr) {
int min = arr[0];
for (int i = 0; i < arr.length; i++) {
if (arr[i] < min) {
min = arr[i];
}
}
return min;
}
/**
* 获取数组的总和
*
* @param arr 要获取总和的数组
* @return 数组的总和
*/
public int sum(int[] arr) {
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}
/**
* 获取数组的平均值
*
* @param arr 要获取平均值的数组
* @return 数组的平均值
*/
public int average(int[] arr) {
return sum(arr) / arr.length;
}
/**
* 遍历数组
*
* @param arr 要遍历的数组
*/
public void printArray(int[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
if (i == 0) {
System.out.print(arr[i]);
} else {
System.out.print(", " + arr[i]);
}
}
System.out.println("]");
}
/**
* 复制数组
*
* @param arr 要复制的数组
* @return 复制出来的数组
*/
public int[] copyArray(int[] arr) {
int[] newArr = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
newArr[i] = arr[i];
}
return newArr;
}
/**
* 数组的反转
*
* @param arr 要反转的数组
*/
public void reverseArray(int[] arr) {
for (int i = 0, j = arr.length - 1; i < j; i++, j--) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
/**
* 数组的排序
*
* @param arr 要排序的数组
*/
public void sortArray(int[] arr) {
//使用冒泡排序
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
/**
* 使用线性查找,查找数组
*
* @param arr 要查找的数组
* @return 返回要查找的数,若未找到,返回-1
* @target 要查找的数
*/
public int searchArray(int[] arr, int target) {
int i = 0;
for (; i < arr.length; i++) {
if (arr[i] == target) {
System.out.println("找到了" + target + ", 对应的位置是 " + i);
return 1;
}
}
if (i == arr.length - 1) {
System.out.println("没找到" + target);
}
return -1;
}
}
创建的对象并调用方法:
public class MethodExer5 {
public static void main(String[] args) {
//根据上一章数组中的常用算法类型:自定义一个操作int[]的工具类
//涉及到的方法有:求最大值,最小值,总和,平均数,遍历数组,复制数组,数组反转
//new一个对象
ArrayAndMethod arr = new ArrayAndMethod();
int [] arr1 = {12,3,432,53,14,43,12,5,24,56,45,42,53};
//通过对象,调用方法
System.out.println(arr.max(arr1));//找出最大值
System.out.println(arr.average(arr1));//平均值
arr.printArray(arr1);//遍历数组
int num = arr.searchArray(arr1,432);
if(num == -1){
System.out.println("未找到");
}
arr.sortArray(arr1);
arr.printArray(arr1);
}
}
对象数组的使用及内存解析:
对象数组:数组的元素可以是基本数据类型,也可以是引用数据类型。当元素是引用数据类型中的类( 类(class),数组(array),接口(interface),枚举(enum),注解(annotation), 记录(record))时,我们称为对象数组
举例:String[], Student[], Customer[]等
练习:
创建的类:
public class Student {
//定义属性
int number;
int state;
int score;
}
创建的对象数组并调用方法:
public class MethodExer6 {
public static void main(String[] args) {
//案例:定义类Student,包含三个属性:学号number(int),年纪state(int),成绩score(int)
//创建20个学生对象,学号为1到20,成绩和年纪都由随机数确定
//问题一:打印3年纪的学生信息
//问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息
//提示:生成随机数:Math.random(),返回值的类型为double
//四舍五入取整:Math.round(double d),返回值类型long
//年纪[1,6]:(int)(Math.random() * 6 +1)
//分数[0,100]:(int)(Math.random() * 101)
//创建对象数组
Student[] students = new Student[20];
//给属性赋值
for(int i = 0; i < students.length; i++ ) {
//创建对象
students[i] = new Student();//初始化每个对象
students[i].number = i + 1;
students[i].score = (int) (Math.random() * 101);//给成绩赋值
students[i].state = (int) (Math.random() * 6 + 1);//给年级赋值
// 打印3年纪学生信息
if (students[i].state == 3) {
System.out.print("该学生的学号是" +students[i].number + "\t");
System.out.println("该学生的成绩是" + students[i].score + "\t");
}
}
System.out.println();
//使用冒泡排序按学生成绩排序,并遍历所有学生信息
for(int i = 0; i < students.length - 1; i++ ) {
for (int j = 0; j < students.length - 1 - i; j++) {
if (students[j].score > students[j + 1].score) {
Student temp;//交换整个,而不只是交换成绩
temp = students[j];
students[j] = students[j + 1];
students[j + 1] = temp;
}
}
}
System.out.println();
for(int i = 0; i < students.length ; i++ ) {
System.out.print("学生的成绩是" + students[i].score + "\t");
System.out.print("学生的学号是" + students[i].number + "\t");
System.out.println("学生的年纪是" + students[i].state + "\t");
}
}
}
内存解析:

方法应用1:方法的重载
定义:在同一个类中,允许存在一个以上的同名方法,只要他们的参数列表不同即可(参数列表不同,意味着参数个数或参数类型的不同)。满足这样特征的多个方法,彼此之间构成方法的重载
总结为:两同一不同
两同:同一个类;相同的方法名
一不同:参数列表不同:1:参数个数不同。2:参数类型不同
重载的特点:与修饰符,返回值类型无关,只看参数列表,且参数列表必须不同。(参数个数或参数类
型)。调用时,根据方法参数列表的不同来区分
重载方法调用:jvm通过方法的参数列表,调用匹配的方法(先找个数,类型最匹配的;再找个数和类型可以兼容的,如果同时多个方法兼容将会报错)
举例:
public class OverLoadTest {
public void add(int i, int j){
}
public void add(int i,int j,int k){
}
public void add(String i, String j){
}
public void add(int i ,String j){
}
//public void add(int m,int i){
//}这个方法就不行,因为参数列表和第一个一样了
}
如何判断两个方法相同?
方法名相同,且形参列表也相同(形参列表相同指的是参数个数和参数类型都相同,与参数名无关)
返回值类型不看
练习:
1.
public class OverLoadExer {
//案例:编写程序:定义三个重载方法并调用,方法名为mOL
//三个方法分别接收一个int参数,两个int参数,一个字符串参数
//分别执行:平方运算并计算结果,相乘并输出结果,输出字符串信息
public void mOL(int n){
System.out.println(n * n);
}
public void mOL(int m,int n){
System.out.println(m * n);
}
public void mOL(String s){
System.out.println(s);
}
}
2.
public class OverLoadExer2 {
//定义三个重载方法max()
//第一个方法求两个int值中的最大值
//第二个方法求两个double值中的最大值
//第三个方法求三个double值中的最大值,并分别调用三个方法
public int max(int x,int y){
int max = (x > y)?x:y;
return max;
}
public void max(double x,double y){
double max = (x > y)?x:y;
System.out.println(max);
}
public void max(int x,int y,double z){
double max = (x > y)?x:y;
double trueMax = (max > z)?max:z;
System.out.println(trueMax);
}
}
面试题:
public class OverLoadExer3 {
public static void main(String[] args) {
int[] arr = new int[]{1,2,3};
System.out.println(arr);//[I@4eec7777
char[] arr1 = new char[]{'z','b','c'};
System.out.println(arr1);//zbc
boolean[] arr2 = new boolean[]{true,false,true};
System.out.println(arr2);//[Z@3b07d329
}
}
方法应用2:可变个数形参的方法
1.使用场景:
在调用方法时,可能会出现方法形参的类型是确定的,但是参数的个数不确定。此时,我们就可以使用可变个数形参的方式
2.格式(参数类型 . . . 参数名)
比如:
public class ArgsTest {
public void print(int ... nums){
}
}
3.说明:
1.可变个数形参的方法在调用时,针对于可变的形参赋的实参个数可以为:0个,1个或多个
2.可变个数形参的方法与同一个类中,同名的多个方法之间可以构成重载
特例:
public void print(int ... nums){
}
public void print(int[] nums){
}//这俩不能构成重载,本质上是一样的
4.可变个数的形参,必须声明在形参列表的最后
public void print(int num,int ... nums){
}
// public void print(int ... n,int num){
//
// }编译不通过
}
5.可变个数的形参,最多在一个方法的形参列表中出现一次
可变参数练习:
public class StringConCatTest {
public static void main(String[] args) {
//新建一个对象
StringConCatTest test = new StringConCatTest();
String info = test.concat("-","hello","world");
System.out.println(info);
}
public String concat(String operator,String ... strs){
String result = "";
for(int i = 0; i < strs.length; i++){
if(i == 0){
result += strs[i];
}else{
result += (operator + strs[i] );
}
}
return result;
}
}
方法引用3:方法值传递机制的剖析(重点):
1.(复习)对于方法内声明的局部变量来说:
public class ValueTransfer {
public static void main(String[] args) {
//1.基本数据类型的局部变量
int m = 10;
int n = m;//传递的是数据值
System.out.println("m: " + m + ", n: " + n);//m:10,n:10
m++;
System.out.println("m: " + m + ", n: " + n);//m:11,n:10
//2.引用数据类型的局部变量(类(class)//数组(array)//接口(interface)//枚举(enum)//注解(annotation)//记录(record))
//2.1数组类型
int[] arr1 = new int[]{1,2,3,4,5};
int[] arr2 =arr1;//没有new,传递的是地址值
arr2[0] = 10;
System.out.println(arr1[0]);//10
//2.2对象类型
Order order1 = new Order();
order1.oderId = 1001;
Order order2 = order1;
order2.oderId = 1002;
System.out.println(order1.oderId);//1002
}
}
class Order{
//定义属性
int oderId;
}
1.1如果是基本数据类型的变量,则将此变量保存的数据值传递出去(可以理解成C语言里的值传递)
1.2如果是引用数据类型的变量,则将此变量保存的地址值传递出去(可以理解成C语言里的址传递)
2.方法的参数的传递机制:值传递机制(存的什么就传递什么,存的数据值就传递数据,存的地址值就传递地址)
2.2规则:实参给形参赋值的过程
2.2.1如果形参是基本数据类型的变量,则将实参保存的数据值赋给形参
2.2.2如果是引用数据类型的变量,则将实参保存的地址值赋给形参
3.面试题:Java中的参数的传递机制是什么?
值传递(不是引用传递)
练习:
public class ValueTransferTest2{
public static void main(String[] args){
ValueTransferTest2 vt2 = new ValueTransferTest2();
int m = 10,n = 20;
System.out.println("m = " + m + ", n = " + n);
//交换两个变量的值
vt2.swap(m,n);
System.out.println("m = " + m + ", n = " + n);
}
public void swap(int m,int n){
int temp = m;
m = n;
n = temp;
}
}
m,n的值最后输出不会交换,因为是在swap里交换的,交换的是swap里定义的局部变量m,n,出了swap后就没用了

练习2:
public class ValueTransferTest3{
public static void main(String[] args) {
ValueTransferTest3 obj = new ValueTransferTest3();
Data1 data = new Data1();
data.m = 10;
data.n = 20;
System.out.println("m = " + data.m + ", n = " + data.n);
obj.swap1(data);
}
public void swap1(Data1 data){
int temp = data.m;
data.m = data.n;
data.n = temp;
System.out.println("m = " + data.m + ", n = " + data.n);
}
}
class Data1{
int m;
int n;
}
m,n的值最后会交换,因为swap1里的形参是地址值,指向了data,所以可以交换

练习:
public class ValueTransferTest4{
public static void main(String[] args) {
//1.定义一个Circle类,包含一个double型的radius属性代表圆的半径,一个findArea()方法返回圆的面积
//
//
//2.定义一个类PassObject,在类中定义一个方法printAreas(),该方法的定义如下:
//public void printAreas(Cirsle2 c,int time)
//
//3.在printAreas方法中打印输出1到time之间的每个整数半径值,以及对应的面积。
//
//4.在main方法中调用printAreas()方法,调用完毕后输出当前半径值
PassObject c1 = new PassObject();
Circle2 c2 = new Circle2();
c1.printAreas(c2,5);
}
}
class PassObject {
public void printAreas(Circle2 c,int time){
for(int i = 1;i <= time;i++){
c.radius = i;
System.out.println(c.radius);
System.out.println(c.findArea());
}
}
}
class Circle2 {
//1.定义一个Circle类,包含一个double型的radius属性代表圆的半径,一个findArea()方法返回圆的面积
//
//
//2.定义一个Circle类,在类中,定义一个方法,printAreas()。该方法的定义如下:
//public void printAreas(Circle c ,int time)
//
//3.在printAreas方法中打印输出1到time之间的每个整数半径值,以及对应的面积。
//
//4.在main方法中调用printAreas()方法,调用完毕后输出当前半径值
//定义属性
double radius;
//定义方法
public double findArea() {
return Math.PI * radius * radius;
}
}
方法应用4:递归
递归方法调用:方法自己调用自己
方法的分类:直接递归,间接递归(a调用b,b调用c,c调用a)
说明:
递归包含了一种隐式的循环
递归方法会重复执行某段代码,但这种重复执行无需循环控制
递归一定要向已知方向递归,否则这种递归就变成了无穷递归,最终会栈内存溢出
举例:
public class RecursionTest {
public static void main(String[] args) {
//获取1-100内自然数的总和
RecursionTest test = new RecursionTest();
System.out.println(test.getSum(100));
System.out.println(test.getMul(5));
System.out.println(test.getDiv(10));
}
public int getSum(int num){
int sum = 0;
if(num == 1){
return 1;
}else{
return getSum(num-1) + num;}
}
public int getMul(int n){
if(n == 1){
return 1;
}else{
return getMul(n-1) * n;
}
}
//斐波那契数列
public int getDiv(int n){
if(n == 1){
return 1;
}else if(n == 2){
return 1;
}else{
return getDiv(n-1) + getDiv(n-2) ;
}
}
}
注意:
1.递归调用会占用大量的系统堆栈,内存耗用多,在递归调用层次多时速度比循环“慢得多”,所以在使用循环时要慎重
2.在要求高性能的情况下尽量避免使用递归
练习:
public class RecusionExer01{
//已知数列:f(20) = 1,f(21) = 4,f(n + 2) = 2 * f(n+1)+ f(n)
//其中n是大于0的整数,求f(10)的值
public static void main(String[] args) {
RecusionExer01 rec = new RecusionExer01();
System.out.println(rec.f(14));
}
public int f(int n){
if(n == 10){
return 1;
} else if (n == 21) {
return 4;
}
else{
return f(n + 2) - 2*f(n + 1);
}
}
}
package关键字的使用:
说明:
package:包,用于指明该文件中定义的类,接口等结构所在的包
语法格式:package 顶层包名.子包名;
说明:
1.一个源文件只能有一个声明包的package语句
2.package语句作为Java源文件的第一条语句出现,如果省略该语句,则指定为无名包
3.包名,属于标识符,满足标识符命名的规则和规范(全部小写)(看到这回去复习一下),见名知意
4.包通常使用所在公司域名的倒置
5.大家取包名的时候不要使用“Java.xx”包
6.包对应文件系统的目录,package语句中使用“.”来指明包(目录)的层次,每.一次就代表一层文件目录
7.同一个包名下可以声明多个结构(类,语句),但是不能定义同名的结构(类,接口),不同的包下可以定义同名的结构(类,接口)
包的作用:
1.包可以包含类和子包,划分“项目层次”,便于管理
2.帮助“管理大型软件”系统:将功能相近的类划分到同一个包中,
3.解决“类命名冲突”的问题
4.控制访问权限
jdk中主要的包:
java.lang
java.net
java.io
java.util
java.spl
java.awt
import关键字的使用:
为了使用定义在其他包中的Java类,需用import语句来显示引用指定包下所需要的类,相当于import语句告诉编译器到哪里去找这个类。
语句格式;
import 包名.类名;
注意事项:
1.import语句,声明在包的声明和类的声明之间
2.如果需要导入多个类或接口,那么久并列显示多个import语句即可
3,如果使用a.*导入结构,表示可以导入a包下的所有的结构。举例:可以使用java.util.*的方式,一次性导入util包下所有的类或接口
4。如果导入的类或接口是java.lang包下的,或者是当前包下的,就可以省略import语句
5.如果已经导入Java.a包下的类,那么如果需要使用a包的子包下的类的话,任然需要导入
6.如果在代码中使用不同包下的同名的类,那么就需要使用类的全类名的方式指明调用的是哪个类
7.(了解)import static组合的使用,调用指定类或接口下的静态的属性或方法
面向对象的特征一:封装性:
1,为什么需要封装性:
理论上:随着项目越来越复杂,类越来越多,那么类之间的访问边界必须把控好,面向对象的开发原则要遵守“高内聚,低耦合”
高内聚:类的内部数据操作细节由自己完成,不允许外界干涉
低耦合:仅暴露少量方法给外部使用,尽量方便外部调用
2.何为封装性:
所谓封装,就是把客观事物封装成抽象类的概念,并且类可以把自己的数据和方法只向可信的类或对象开放,向没必要开放的类或者对象隐藏信息。
通俗来讲,把该隐藏的隐藏起来,把该暴露的暴露出来,这就是封装性的设计思想
3.如何实现数据封装
3.1权限修饰符:
Java规定了四种权限修饰符,分别是:private,缺省,protected,public

3.2作用:
可是使用四种权限修饰符修饰类及类的内部成员,当这些成员被调用时,体现可见性的大小
3.3实例说明
package AniMalTest;
/**
* ClassName:AniMalTest
* Package:AniMalTest
* Description:
*
* @Author 妄汐霜
* @Create 2025/11/3 21:19
* @Version 1.0
*/
public class AniMalTest {
public static void main(String[] args) {
AniMal animal1 = new AniMal();
animal1.name = "长颈鹿";
animal1.legs = 3;
//此时的legs就不能再调用了,因为AniMal方法中的legs已经私有化,不能再调用了
//只能通过调用方法来调用legs
animal1.setLegs(animal1.legs );
System.out.println("name = " + animal1.name + ",legs = " + animal1.legs);
animal1.eat();
}
}
class AniMal{
//属性
String name;
private int legs;
//方法
public void eat(){
System.out.println("动物觅食");
}
public void setLegs(int l){
if(l >= 0 && l % 2 == 0){
l = legs;
}else{
System.out.println("输入的数据有误");
}
}
}
另外再定义一个方法后就可以调用legs了
public int getLegs(){
return legs;
}
在题目中,我们给Animal的对象的legs属性赋值。在实际的常识中,我们知道legs不能赋值为负数的,但是如果直接调用legs,是不能加入判断语句的,那该怎么办:
1.将legs属性私有化(private),再另外设置另一个方法用来调用或者给legs属性赋值,在这个方法中加入判断语句
3.4 4种 权限具体使用情况
类,只能用public ,缺省修饰
类的内部成员,就可以用四种权限修饰符进行修饰
练习:
创建的类:
public class Person {
private int age;
public void setAge(int a) {
if(a >= 0 && a <= 130 ){
age = a;
}else{
System.out.println("输入非法");
}
}
public int getAge() {
return age;
}
}
对象:
public class PersonTest {
public static void main(String[] args) {
Person person = new Person();
person.setAge(20);
System.out.println(person.getAge());
}
}
练习2:
创建的类:
public class Book {
//定义属性
private String title;//标题
private String author;//作者
private int price;//价格
//定义方法来获取
public String getTitle() {
return title;
}
public String getAuthor() {
return author;
}
public int getPrice() {
return price;
}
public void setTitle(String title) {
this.title =title;
}
public void setAuthor(String author) {
this.author =author;
}
public void setPrice(int price) {
this.price =price;
}
}
创建的对象:
public class BookTest {
public static void main(String[] args) {
Book book = new Book();
book.setAuthor("妄汐霜");
book.setPrice(9999);
book.setTitle("颠虚自守");
System.out.println(book.getAuthor());
System.out.println(book.getPrice());
System.out.println(book.getTitle());
}
}
练习3:
创建的类;
public class Employee {
//定义属性
private String name;
private char gender;
private int age;
private String phoneNumber;
public void setName(String name) {
this.name = name;
}
public void setGender(char gender) {
this.gender = gender;
}
public void setAge(int age) {
this.age = age;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getName() {
return name;
}
public char getGender() {
return gender;
}
public int getAge() {
return age;
}
public String getPhoneNumber() {
return phoneNumber;
}
public String getInfo() {
return name + "\t " + gender + "\t " + age + "\t " + phoneNumber;
}
}
对象:
public class EmployeeTest {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Employee[] emp = new Employee[2];
for(int i = 0; i < emp.length; i++){
emp[i] = new Employee();
System.out.println("添加第" + (i + 1)+ "个员工的信息");
System.out.println("姓名");
String name = sc.next();
System.out.println("性别");
char gender = sc.next().charAt(0);
System.out.println("年龄");
int age = sc.nextInt();
System.out.println("电话");
String phoneNumber = sc.next();
//给数组元素赋值
emp[i].setName(name);
emp[i].setGender(gender);
emp[i].setAge(age);
emp[i].setPhoneNumber(phoneNumber);
}
//遍历输出数组的元素
for(int i = 0; i < emp.length; i++){
System.out.println(emp[i].getInfo());
}
}
}
类的成员之三:构造器(constructor):
1.构造器的理解
凡是类都有构造器
2.构造器的作用:
作用1:搭配new关键字,创建类的对象
举例:Person person = new Person();
![]()
末尾带()的就是构造器
作用2:在创建对象的同时,可以给对象的相关属性赋值
3.构造器的使用:
格式:
权限修饰符 类名(形参列表){}
比如::
}
说明:
1.创建类以后,在没有显示提供任何构造器,系统会提供一个空参的构造器,且构造器的权限和类声明的权限相同。
2.一旦类中显示显示声明了构造器,则系统不在提供默认的空参的构造器
3.一个类中可以声明多个构造器,这就是构造器重载
实例变量赋值过程:
1.在类的属性中,可以有哪些位置给属性赋值:
1.默认赋值
2.显式赋值:
3.构造器中赋值
4.通过“对象.方法”的方式赋值。
5.通过“对象.属性”的方式赋值
2.这些位置执行的先后顺序:
1 ->2->3->4/5
3.以上操作在对象创建过程中可以执行的次数如何?
1.2.3只能执行一次
4.5能多次赋值
JavaBean:
Javabean是一种java语言写成的可重用组件
JavaBean指的是符合如下标准的Java类:
类是公共的
有一个无参的公共的构造器
有属性,有对应的get,set方法
举例:
public class Customer1 {
//公共的空参构造器
public Customer1(){
}
//属性
private int id;
private String name;
//属性对应的set,get方法
public void setID(int i){
id = i;
}
public int getID(){
return id;
}
public void setName(String n){
name = n;
}
public String getName(){
return name;
}
}
读懂UML类图:
UM(统一建模语言),用来描述软件模型和架构的图形化语言
在软件开发中,使用UML类图可以更加直观地描述类内部结构(类的属性和方法)以及类之间的关系

本节梗概:
/*
1.面向过程和面向对象
不管是面向过程还是面向对象,都是程序设计的思路
面向过程:以函数为基本单位,适合简单问题
面向对象:以类为基本单位,适合解决复杂问题
2.类,对象
类:抽象的概念
对象:具体的类的实例
关于对象的内存解析:
创建类的一个对象
创建类的多个对象
Java中内存结构的划分:虚拟机栈,本地方法栈,堆,方法区,程序计数器,本地方法栈
虚拟机栈:以栈帧为基本单位,有入栈和出栈的操作;每个栈帧的出入站都对应一个方法的执行和结束;方法中的变量会存储在栈帧里。
堆空间:new出来的结构都在堆空间里:1,数组的元素都在堆中。2,对象的成员变量(属性)都在堆空间中
方法区:加载的类的模板结构
面向对象的编程步骤:
1.创建类
2.创建类的对象
3.通过对象调用方法
3.类的成员之一:属性(成员变量)
属性和局部变量的对比:
声明的位置不同
内存中存放的位置不同
作用域不同
权限修饰符不同
初始化值
生命周期不同
属性也称成员变量,字段,域等
4.类的成员之二:方法
方法声明:权限修饰符 返回值类型 方法名(形参列表){
方法体
}
重点:返回值类型,形参列表
return关键字的使用
5.再谈方法:
5.1方法的重载
方法重载的要求:两同一不同:类和方法名相同,形参列表不同
调用方法时,如何确定调用的是指定的方法?
1.方法名2.形参列表
5.2可变个数形参的方法
格式:(int ... args)
5.3方法的参数传递机制
值传递:如果形参是基本数据类型变量,则将实参中保存的数据值传给形参
如果形参是引用数据类型变量,则将实参中保存的地址值传给形参
5.4递归方法
方法自己调用自己,构成隐式的循环,内存占用偏高
6.对象数组的使用
String[] Customer[]
7.package,import关键字的使用
package:指明声明的类所属的包
import:当前类中如果使用其他包内的类,就要导包
8.面向对象的特征之一:封装性
Java中规定了四种权限修饰符,可以用4种权限修饰符来修饰类及类中的内部成员。当这些内部成员被调用时,体现可见性大小
比如: 私有化属性,提供公共的方法get,set方法,对此属性进行修改或获取
封装性体现了高内聚,低耦合的程序设计的原则
9.类的成员之三:构造器
格式:权限修饰符 类名(形参列表){
}
搭配new用来创建对象,初始化对象的成员变量
10。三个小知识
10.1 类的实例变量的赋值过程
10.2JavaBean
10.3UML图
企业真题:
对象存在Java内存的哪块区域里面?
堆空间。
main方法的public能不能换成private?为什么?
可以改,但是改过之后的main方法就不能作为程序的入口了,就只是一个普通的方法。
构造方法(构造器)和普通方法的区别?
从编写代码的角度:没有共同点。没有共同点,声明格式,作用都不同
从字节码文件的角度:构造器会以init()方法的形态呈现,用以初始化对象
构造器是否可以被重载?
可以。
1210

被折叠的 条评论
为什么被折叠?



