*.学习面向对象(OOP)内容的三条主线
1.java类及类的成员
类和对象是java的两大要素
类的成员:属性、方法、构造器;代码块、内部类
2.面向对象的三大特征
封装性、继承性、多态性(抽象性)
3.其他关键字
this/super/stataic/final/abstract/interface/package/import
4 - 1 面向过程(POP)和面向对象(OOP)
面向过程以函数为基本单位:考虑怎么做;
面向对象以类/对象为基本单位:考虑谁来做;
4 - 2 Java语言的基本要素:类和对象
1.类的成员:属性、方法、构造器;代码块、内部类
1.属性:
对应类中的成员变量
属性 = 成员变量 = field = 域、字段
调用属性:对象.属性
2.方法:
等于函数
调用方法:对象.方法
创建类的对象 == 类的实例化
2.类的使用:
1)创建类,设计类的成员
类中属性的使用:
属性(成员变量) vs 局部变量
1.相同点:
1.1定义变量的格式相同
1.2先声明后使用
1.3变量都有其对应的作用域
2.不同点:
2.1在类中声明的位置的不同
属性:直接定义在一对{}内
局部变量:定义在方法内、方法形参、代码块内、构造器形参、构造器内部的变量
2.2关于权限修饰符的不同
属性:可以在声明属性时,指明其权限,使用权限修饰符。
常用的权限修饰符:private/public/缺省(默认)、proteceted
局部变量:不可以使用权限修饰符
2.3默认初始化值的情况
属性:类的属性根据其类型都有默认初始化值
局部变量:没有默认初始化值 --->意味着在调用时必须有初始化值
2.4在内存中加载的位置不同
属性(非static):加载在堆空间中
局部变量:在栈空间中
类中方法的使用:
描述类中应有的功能
1.举例:public void eat(){}
public void sleep(int hour){}
public String getNation(String nation){}
2.方法的声明:权限修饰符 返回值类型 方法名(形参列表){
方法体
}
注意:static /final/abstract 来修饰的方法,后面讲
3.说明:
3.1 关于权限修饰符:
private/public/缺省/protected
3.2 返回值类型:与方法声明时的返回值类型相同
3.3 方法名:属于标识符,符合标识符的命名规范
3.4 形参列表:方法可以声明0个,1个或多个形参
格式: 数据类型1 形参1,数据类型2 形参2,......
4.return 的作用
1.使用范围:使用在方法体中
2.作用:①结束方法
②针对有返回值类型的方法,使用“return”方法返回所要的数据
3.注意点:return后面不可以有语句
5.方法的使用中,可以调用当前类的属性 和 方法(方法A中又调用了方法A:递归方法)
注意:方法中不可以定义方法
2)创建类的对象
3)通过“对象.属性”/“对象.方法”调用对象的结构
如果创建了一个类的多个对象,则每个对象都独立地拥有一套类的非static属性
3.对象的内存解析
4.练习
练习2:
练习3:
练习4:
package com.atguigu.exer; public class Review1 { public static void main(String[] args) { Student[] stus = new Student[20]; for(int i = 0;i < stus.length;i++) { stus[i] = new Student(); stus[i].number = (int)(Math.random() * 20 + 1); stus[i].state = (int)(Math.random() * 6 + 1); stus[i].score = (int)(Math.random() * 101); } Review1 revi = new Review1(); revi.sortState(stus,3);//输出n年级学生信息 revi.bubbleSort(stus);//冒泡排序 revi.print(stus); } // public void sortState(Student[] stus, int n) { for(int i = 0;i < stus.length;i++) { if(stus[i].state == n) { System.out.println("年级" + stus[i].state + "学号: " +stus[i].number + "成绩" + stus[i].score ); } } } //输出学生信息 public void print(Student[] stus) { for(int i = 0;i < stus.length;i++) { System.out.println("年级" + stus[i].state + "学号: " +stus[i].number + "成绩" + stus[i].score ); } } //冒泡排序 public void bubbleSort(Student[] stus) { 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) { Student temp = stus[j]; stus[j] = stus[j + 1]; stus[j + 1] = temp; } } } } } class Student { int number; int state; int score; }
总结:万事万物皆对象
1.在Java语言范畴中,我们都将功能、结构等封装到类中,通过类的实例化,来调用具体的功能结构
2.涉及到Java语言与前端HTML、后端的数据库交互时,前后端的结构在Java层面交互时,都体现为类和对象
4 - ***
1.匿名对象
package com.atguigu.java; /** *一、万事万物皆对象的理解 * *二、内存解析的说明 * * 1.引用类型的变量,只可能存储两类值:null 或地址值 * *三、匿名对象的使用 * * * */ public class InstanceTest { public static void main(String[] args) { Phone p = new Phone(); 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(p); mall.show(new Phone());//当方法形参类型为另外的类时,可以直接new一个匿名对象 } } 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 - 6 再谈方法
1.方法的重载
1.“两同一不同”:同一个类,同一个方法名;
参数列表不同:参数个数,参数类型不同
2.判断是否为重载:跟权限修饰符,返回值类型,形参变量名,方法体都没有关系
3.在通过对象调用方法时,如何确定某一个指定的方法:
① 方法名--> ② 参数列表
package com.atguigu.exer; public class OverLoadExer { public static void main(String[] args) { OverLoadExer ove = new OverLoadExer(); ove.mOL(4); ove.mOL(4, 6); ove.mOL("乌拉"); } public void mOL(int i) { System.out.println(i * i); } public void mOL(int i, int j) { System.out.println(i * j); } public void mOL(String str) { System.out.println(str); } }
2.可变个数形参的方法
2.1可变个数形参的格式:
public void show (String ...strs) { }
2.2当调用可变个数个形参的方法时,传入的参数个数可以是任意个
2.3可变个数个形参之前版本以传入相同类型的数组作为形参来代替
其引用方法和相同类型的数组完全相同
2.5可变个数的形参在方法的形参中,只能声明在末尾
且一个方法的形参中只能含有一个可变个数的形参
3.方法参数的值传递机制
package com.atguigu.java1; /** * 方法的形参的传递机制:值传递 * * 1.形参:方法定义时,声明的小括号内的参数 * 实参:方法调用时,实际传递给形参的数据 * * 2.值传递机制: * * */ public class ValueTransferTest1 { public static void main(String[] args) { //交换两个变量的值: int m = 10; int n = 20; System.out.println("m = " + m + ", n = " + n); //交换两个变量的值的操作 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; } }
package com.atguigu.java1; public class ValueTransferTest2 { public static void main(String[] args) { Data data = new Data(); data.m = 10; data.n = 20; System.out.println("m = " + data.m + ", n = " + data.n); ValueTransferTest2 test = new ValueTransferTest2(); test.swap(data); System.out.println("m = " + data.m + ", n = " + data.n); } public void swap(Data data) { int temp = data.m; data.m = data.n; data.n = temp; } } class Data { int m; int n; }
练习:
package com.atguigu.exer; public class Circle { public static void main(String[] args) { Circle c = new Circle(); PassObject test = new PassObject(); test.printAreas(c, 5); } double radius; public double findArea(double radius) { double area = radius * radius * 3.14; return area; } } class PassObject { public void printAreas(Circle c,int time) { System.out.println("Radius Area"); for(int i = 1;i <= time;i++) { c.radius = i; System.out.println(c.radius + " " + c.findArea(c.radius)); } } }
4.递归方法
一个方法调用其本身
注意:递归一定要方向递归,不要无限递归
package com.atguigu.java1; public class RecursionTest { public static void main(String[] args) { RecursionTest test = new RecursionTest(); int sum1 = test.getSum(100); System.out.println(sum1); long product1 = test.getProduct(4); System.out.println(product1); int fx = test.getValue(4); System.out.println(fx); } //例1:计算1-n之间所有自然数的和 public int getSum(int n) { if(n == 1) { return 1; }else{ return n + getSum(n - 1); } } //例2:计算1-n之间所有自然数的和 public long getProduct(int n) { if(n == 1) { return 1; } else { return n * getProduct(n - 1); } } //例3: public int getValue(int n) { if(n > 0) { if(n == 0) { return 1; } else if(n == 1) { return 4; } else { return 2 * getValue(n - 1) + getValue(n - 2); } } else { return 0; } } }
4 - 7 面向对象特征之一:封装与隐藏
1、问题的引入:
当我们创建一个类的对象以后,我们可以通过"对象.属性"的方式,对对象的属性进行赋值。这里,赋值操作收到属性的数据类型和存储范围制约,但除此之外,没有其他制约条件。但是,在实际问题中,我们往往需要给属性赋值加入额外的限制条件。这个条件就不能在属性声明是体现,我们只能通过方法进行限制条件的添加。同时,我们需要避免用户再使用“对象.属性”的方式对属性进行赋值。则需要将属性声明为私有的(private)-->此时,针对属性就体现了封装性
2、封装性的体现
①我们将类的属性私有化(private),同时,提供公共的方法set和get类的值
②不对外暴露的方法
③单例模式
3、封装性的体现,需要权限修饰符来配合
1.Java规定的四种权限(小-->大)
private、缺省、protected、public
练习:
package com.atguigu.exer; public class Person { private int age; public void setAge(int i) { age = i; } public int getAge() { return age; } } public class PersonTest { public static void main(String[] args) { Person b = new Person(); b.setAge(18); int age = b.getAge(); System.out.println(age); } }
4 - 8 类的成员之三:构造器
1、构造器的作用:
1).创建对象
2).初始化创建对象的属性
2、说明:
1).如果没有显式的定义类的构造器的话,则系统默认提供一个空参的构造器
2).定义构造器的格式:权限修饰符 类名 形参列表(){}
3).一个类中定义的多个构造器,彼此构成重载
4).一旦我们显式的定义了类的构造器之后,系统就不再提供默认的空参构造器
5).一个类中至少会有一个构造器
练习:
1).
package com.atguigu.exer; public class Person { private int age; private String name; //构造器 public Person() { age = 18; } public Person(String n,int i) { name = n; age = i; } //方法 public void setAge(int i) { if(i < 0 || i > 130) { System.out.println("传入的数据非法"); } else { age = i; } } public int getAge() { return age; } public void setName(String n) { name = n; } public String getName() { return name; } }
package com.atguigu.exer; public class PersonTest { public static void main(String[] args) { Person b = new Person(); b.setAge(18); int age = b.getAge(); System.out.println(age); Person b1 = new Person("Tom",18); System.out.println(b1.getAge()); System.out.println(b1.getName()); } }
2).
package com.atguigu.exer1; public class TriAngle { private double base; private double height; public TriAngle() { } public TriAngle(double b,double h) { base = b; height = h; } public void setBase(double b) { base = b; } public double getBase() { return base; } public void setHeight(double h) { height = h; } public double getHeight() { return height; } }
package com.atguigu.exer1; public class TriAngleTest { public static void main(String[] args) { TriAngle tri1 = new TriAngle(); tri1.setBase(2.0); tri1.setHeight(3.0); System.out.println("base: " + tri1.getBase() + ", height: " + tri1.getHeight()); // TriAngle tri2 = new TriAngle(5.1, 5.6); System.out.println("base: " + tri1.getBase() + ", height: " + tri1.getHeight()); } }
3).
package com.atguigu.exer2; public class Student { private String name; private int age; private String school; private String major; public Student(String n,int a) { name = n; age = a; } public Student(String n, int a,String s) { name = n; age = a; school = s; } public Student(String n, int a,String s, String m) { name = n; age = a; school = s; major = m; } public String getName() { return name; } public int getAge() { return age; } public String getSchool() { return school; } public String getMajor() { return major; } }
package com.atguigu.exer2; public class StudentTest { public static void main(String[] args) { Student stu1 = new Student("Mbappe",22); System.out.println("Student: " + stu1.getName() + ", age: " + stu1.getAge()); Student stu2 = new Student("Halland", 20, "Norway"); System.out.println("Student: " + stu2.getName() + ", age: " + stu2.getAge() + ", school: " + stu2.getSchool()); Student stu3 = new Student("Vlahovic", 27, "Sewiria", "football"); System.out.println("Student: " + stu3.getName() + ", age: " + stu3.getAge() + ", school: " + stu3.getSchool() + ", major: " + stu3.getMajor()); } }
3、总结:属性赋值的先后顺序
① 默认初始化值
②显式初始化
③构造器中赋值
④通过"对象.方法"或"对象.属性"
以上操作的先后顺序 ① - ② - ③ - ④
4、JavaBean
5. UML类图
4 - 9 关键字:this的调用
1.this 可以用来修饰、调用:
属性、方法、构造器
2.this修饰属性和方法:
this 理解为:当前对象
1)在类的方法中,我们可以使用"this.属性"this.方法"的方式,调用当前对象属性或方法。
通常情况下,我们都选择省略"this."。特殊情况下,如果方法的形参和类的属性同名时,我们必须显式的使用"this.变量"的方式,表明此变量是属性,而非形参
2)在类的构造器中,我们可以使用"this.属性"this.方法"的方式,调用当前正在创建的对象属性或方法。
通常情况下,我们都选择省略"this."。特殊情况下,如果方法的形参和类的属性同名时,我们必须显式的使用"this.变量"的方式,表明此变量是属性,而非形参
3.this 来修饰构造器
①我们在类的构造器中,可以显式的使用"this(形参列表)"方式,调用本类中的其他构造器
②构造器中不能通过"this(形参列表)"来调用自己
③如果一个类中有n个构造器,最多有n - 1个构造器使用“this(形参列表)”
④规定:"this(形参列表)"必须声明在当前构造器的首行
⑤构造器内部 : 最多只能声明一个"this(形参列表)"
练习:
package com.atguigu.exer3; public class Boy { private String name; private int age; public Boy() { } public Boy(String name,int age) { this.name = name; this.age = age; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public int getAge() { return age; } public void marry(Girl girl) { System.out.println("我想娶" + girl.getName()); } public void shout() { if(age >= 22) { System.out.println("你可以去合法登记结婚了!"); } else { System.out.println("先多谈一谈恋爱"); } } }
package com.atguigu.exer3; public class Girl { private String name; private int age; public Girl() { } public Girl(String name,int age) { this.name = name; this.age = age; } public void setName(String name) { this.name = name; } public String getName() { return name; } public void marry(Boy boy) { System.out.println("我想嫁给" + boy.getName()); boy.marry(this); } //比较两个对象的大小:正数:当前对象大,负数:当前对象小,0:当前对象与形参对象相等 public int compare(Girl girl) { return this.age - girl.age; } }
package com.atguigu.exer3; public class BoyGrilTest { public static void main(String[] args) { Boy boy = new Boy("Mbappe",21); boy.shout(); Girl girl = new Girl("Rose",18); girl.marry(boy); } }
*.练习
4 - 10 import package关键字的引用
1.package的使用
1)为了更好地实现项目中类的管理,提供包的概念
2)使用package声明类或接口所属的包,声明在源文件的首行
3)包,属于标识符,遵循标识符的命名规则和规范、(xxxyyyzzz)“见名知意”
4)每“.”一次,就代表一层文件目录
2.JDK中主要的包介绍
3.MVC设计模式
4.import关键字的使用
1)在源文件中显式的使用import结构导入指定包下的类、接口
2)声明在包的声明和类的声明之间
3)如果需要导入多个结构,并列的写出即可
4)可以使用"xxx.*"的方式表示可以导入xxx下的所有结构
5)如果使用的类或接口时java.lang包下的,可以省略import结构
6)如果使用的类或接口时本包下定义的,则可省略import结构
7)如果在源文件中,使用了不同包下的同名的类,则必须至少有一个类以全类名的方式导用
8)使用“xxx.*”方式表明可以调用xxx包下的所有结果。但是如果使用xxx子包下的结构,则需重新导入此结构
9)import static:导入指定类或接口中的静态结构
4 - * 快捷键的使用
/*
* Eclipse中的快捷键:
* 1.补全代码的声明:alt + /
* 2.快速修复: ctrl + 1
* 3.批量导包:ctrl + shift + o
* 4.使用单行注释:ctrl + /
* 5.使用多行注释: ctrl + shift + /
* 6.取消多行注释:ctrl + shift + \
* 7.复制指定行的代码:ctrl + alt + down 或 ctrl + alt + up
* 8.删除指定行的代码:ctrl + d
* 9.上下移动代码:alt + up 或 alt + down
* 10.切换到下一行代码空位:shift + enter
* 11.切换到上一行代码空位:ctrl + shift + enter
* 12.如何查看源码:ctrl + 选中指定的结构 或 ctrl + shift + t
* 13.退回到前一个编辑的页面:alt + left
* 14.进入到下一个编辑的页面(针对于上面那条来说的):alt + right
* 15.光标选中指定的类,查看继承树结构:ctrl + t
* 16.复制代码: ctrl + c
* 17.撤销: ctrl + z
* 18.反撤销: ctrl + y
* 19.剪切:ctrl + x
* 20.粘贴:ctrl + v
* 21.保存: ctrl + s
* 22.全选:ctrl + a
* 23.格式化代码: ctrl + shift + f
* 24.选中数行,整体往后移动:tab
* 25.选中数行,整体往前移动:shift + tab
* 26.在当前类中,显示类结构,并支持搜索指定的方法、属性等:ctrl + o
* 27.批量修改指定的变量名、方法名、类名等:alt + shift + r
* 28.选中的结构的大小写的切换:变成大写: ctrl + shift + x
* 29.选中的结构的大小写的切换:变成小写:ctrl + shift + y
* 30.调出生成getter/setter/构造器等结构: alt + shift + s
* 31.显示当前选择资源(工程 or 文件)的属性:alt + enter
* 32.快速查找:参照选中的Word快速定位到下一个 :ctrl + k
*
* 33.关闭当前窗口:ctrl + w
* 34.关闭所有的窗口:ctrl + shift + w
* 35.查看指定的结构使用过的地方:ctrl + alt + g
* 36.查找与替换:ctrl + f
* 37.最大化当前的View:ctrl + m
* 38.直接定位到当前行的首位:home
* 39.直接定位到当前行的末位:end
*/