Javase||四、面向对象(上)
文章目录
1、类和对象
类:抽象概念的人
对象:实实在在的人
1.1类和对象的创建
步骤(面向对象思想落地的实现:
1、创建类、设计类的成员
2、创建类的对象
3、通过“对象.属性”或“对象.方法”调用对象的结构
体会类的多个对象的关系:如果创建了一个类的多个对象,则每个对象都独立的拥有一套类的属性(非static的), 意味着如果我们修改一个对象的属性a,则不影响另外一个对象属性a的值
创建类:
class Person {
//属性
String name;
int age = 1;
boolean isMale;
//方法
public void eat() {
System.out.println("爱吃蔬菜");
}
public void sleep() {
System.out.println("不熬夜");
}
public void language(String talk) {
System.out.println("李华可以说话,使用的是:"+talk);
}
}
创建类的对象:
public class PersonTest {
public static void main(String[] args) {
//创建Person类的对象
Person p1 = new Person();
//Scanner scanner = new scanner(system.in);
//调用对象的结构:属性、方法
//调用属性:“对象.方法”
p1.name = "李华";
p1.age = 23;
p1.isMale = true;
System.out.println(p1.name);
//调用方法,“对象.方法”
p1.eat();
p1.sleep();
p1.language("中文");
1.2JVM内存结构
略
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gmXF5Eqi-1650111114178)(D:\Liqingq\techique\markdown_notebook\学习\java\学习配图\IJW%B5RK9IR{JOC[FCV87.png)]
1.3匿名对象
定义:我们创建的对象,没显示的赋给一个变量名。即为匿名对象
特点:匿名对象只能调用一次
举例:
new Phone().price=1999;
new Phone().showPrice();//0.0
应用场景:
public class InstanceTest {
public static void main(String[] args) {
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);
}
}
2、类的结构之一:属性
类的结构:属性和方法
设计类就是设计类的成员:
-
属性 = 成员变量 = field
-
方法 = 成员变量 = 函数 = method
-
创建类的对象 = 类的实例化 = 实例化类
/*如果创建了一个类的多个对象,则每个对象都独立的拥有一套类的属性(非static的) 意味着如果我们修改一个对象的属性a,则不影响另外一个对象属性a的值*/
这里注意不同点,成员变量直接定义在类的一对{}内;
局部变量:声明在方法内、方法形参、代码块内、构造器内部的
属性默认初始化值情况
类的属性,根据其类型,都有默认初始化值;
局部变量没有默认初始化值,故调用局部变量之前,一定要显示赋值,特别的,形参在调用时,我们赋值
2.1(成员变量)属性与局部变量的对比
-
相同点:
- 定义变量格式相同:数据类型 变量名 = 变量值
- 先声明后使用
- 变量都有其对应的作用域
-
不同点
2.1类中声明位置不同:属性:直接在类的{}中;局部变量:声明在方法内、方法形参、代码块形参、构造器内部的变量
2.2权限修饰符不同
属性:可以在声明时,指明其权限,使用权限修饰符
java规定的4中权限修饰符:private、public 、缺省、protectd
2.3默认初始化值情况:
属性:类的属性,根据其类型,都有默认初始化值
整型(byte、short、int、long) : 0
浮点型(float、doble):0.0
字符型(char):0(或’\u0000‘)
布尔型(boolean):false
引用数据类型(类、数组、接口):null
局部变量,没有初始化值(意味着,在调用局部变量之前,一定要显示赋值。
特别的,形参在调用时,我们赋值即可。
2.4 内存加载位置:
属性:加载在堆空间中(非static)
局部变量:加载在栈空间中
3、类的结构之二:方法
1、方法:描述类应该具有的功能
比如:Math类:sqrt()\random()\...
Scanner类:nextxxx()
Arrays类:sort()\binarySeach()\toString\equals()\...
2、方法分类:
无返回值 有返回值
无形参 void方法名(){} 返回值的类型方法名(){}
有形参 void方法名(形参列表){} 返回值的类型方法名(形参列表){}
举例:
public void eat(){}
public void sleep(int hour){}
public String getName(){}
public String getNation(String nation) {}
形
3、方法的声明:权限修饰符 返回值类型 方法名(形参列表){
方法体
}
注意:static、final、abstrat来修饰的方法(权限修饰符)
4、说明:
4.1关于权限修饰符,默认方法的权限修饰符先都使用public
java规定的4中权限修饰符:private、public 、缺省、protectd
4.2返回值类型:有返回值vs无返回值
4.2.1如果方法有返回值,则必须再方法生命时,指定返回值的类型,同时,方法中,
需要使用return关键字来返回指定类型的变量或常量。
如果方法中没有返回值,则方法声明时2,使用void来表示,没有返回值的方法中,就不使用
return,但是,如果使用的话,只能“return"表示此方法结束的意思。
4.2.2我们定义方法时,该不该有返回值?
1、题目要求
2、凭经验,具体问题具体分析
4.3方法名:属于标识符,遵循标识符的规则和规范,“见名之意”
4.4形参列表:方法可以声明0个,1个,或多个
4.4.1格式:数据类型1 形参1,数据类型2,形参2,···
4.4.2我们定义方法时,该不该定义形参
1.题目要求
2.凭经验
3.1方法举例与声明的方式
1、方法:描述类应该具有的功能
比如:Math类:sqrt()\random()\...
Scanner类:nextxxx()
Arrays类:sort()\binarySeach()\toString\equals()\...
2、方法分类:
无返回值 有返回值
无形参 void方法名(){} 返回值的类型方法名(){}
有形参 void方法名(形参列表){} 返回值的类型方法名(形参列表){}
举例:
public void eat(){}
public void sleep(int hour){}
public String getName(){}
public String getNation(String nation) {}
形
3、方法的声明:权限修饰符 返回值类型 方法名(形参列表){
方法体
}
注意:static、final、abstrat来修饰的方法
4、说明:
4.1关于权限修饰符,默认方法的权限修饰符先都使用public
java规定的4中权限修饰符:private、public 、缺省、protectd
4.2返回值类型:有返回值vs无返回值
4.2.1如果方法有返回值,则必须再方法生命时,指定返回值的类型,同时,方法中,
需要使用return关键字来返回指定类型的变量或常量。
如果方法中没有返回值,则方法声明时2,使用void来表示,没有返回值的方法中,就不使用
return,但是,如果使用的话,只能“return"表示此方法结束的意思。
4.2.2我们定义方法时,该不该有返回值?
1、题目要求
2、凭经验,具体问题具体分析
4.3方法名:属于标识符,遵循标识符的规则和规范,“见名之意”
4.4形参列表:方法可以声明0个,1个,或多个
4.4.1格式:数据类型1 形参1,数据类型2,形参2,···
4.4.2我们定义方法时,该不该定义形参
1.题目要求
2.凭经验
return关键字的作用:
1.使用范围:方法体中
2.作用:2.1 结束方法
2.2针对有返回值类型的方法,使用return数据方法返回所要的数据
3.注意:return关键字后面不可以声明执行语句
5.方法的使用中,可以调用当前类的属性或方法
特殊的:方法A中又调用了方法A(递归方法)
练习
public class StudentTest {
public static void main(String[] args) {
Student[] stus = new Student[20];//Student类型的数组,与String[] stus = new student[20]一样的意思
for (int i = 0; i < stus.length; i++) {
//给数组元素赋值
stus[i] = new Student();//给每个数组位置new一个对象
stus[i].number = i + 1;
stus[i].score = (int) (Math.random() * (100 - 0 + 1));
stus[i].state = (int) (Math.random() * (6 - 1 + 1) + 1);
}
StudentTest s1 = new StudentTest();
s1.print(stus);
s1.searchState(stus, 3);
s1.sort(stus);
s1.print(stus);
}
//遍历学生数组
public void print(Student[] stus) {//传入要打印的数组
for (int i = 0; i < stus.length; i++) {
System.out.println(stus[i].info());
}
}
public void searchState(Student[] stus, int state) {
System.out.println("**************************");
for (int i = 0; i < stus.length; i++) {
if (stus[i].state == 3) {
System.out.println("number:" + stus[i].number + ",state" + stus[i].state
+ ",score" + stus[i].score);
}
}
}
public void sort(Student[] 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) {
Student temp = stus[j];
stus[j] = stus[j + 1];
stus[j + 1] = temp;
}
}
}
}
}
class Student {
int number;
int state;
int score;
public String info() {
return "number:" + number + ",state" + state
+ ",score" + score;
}
}
3.1关键字return
return关键字的作用:
1.使用范围:方法体中
2.作用:
2.1 结束方法
2.2针对有返回值类型的方法,使用return数据方法返回所要的数据
3.注意:return关键字后面不可以声明执行语句
3.2方法的重载
重载的概念:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数
类型不同即可。
//重载
public void getSum(int i, int j) {
System.out.println("1");
}
public void getSum(double d1, double d2) {
System.out.println("2");
}
public void getSum(String s, int i) {
System.out.println("3");
}
3.3可变参数个数形参的方法
- 声明格式:方法名(参数的类型名 …参数名)
- 可变参数:方法参数部分指定类型的参数个数是可变多个:0个,1个或多个
- 可变个数形参的方法与同名的方法之间,彼此构成重载
- 方法的参数部分有可变形参,需要放在形参声明的最后
- 在一个方法的形参位置,最多只能声明一个可变个数形参
public void show(String s){
System.out.println("show(String)");
}
//可变个数的形参,与上面的show()方法构成重载
public void show(String...strs){
System.out.println("show(String...strs)");
}
// public void show(String [] str){
//
// }此方法与可变个数的形参认为是一样的,不构成重载
//注意:如果有个方法,方法名和上面一样,但是,形参是有限个,优先调用有限个的方法
}
3.4java的值传递机制(注意理解)
==待理解:视频p213练习继续敲代码=
Java的实参值如何传入方法呢?
Java里方法的参数传递方式只有一种:值传递。 即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。
- 形参是基本数据类型:将实参基本数据类型变量的“数据值”传递给形参
- 形参是引用数据类型:将实参引用数据类型变量的“地址值”传递给形参
- 注意String类型虽然它是引用类型,但是实际上它是基本数据类型的使用方法,传值
基本数据类型:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DtlxcLfX-1650111114179)(D:\Liqingq\techique\markdown_notebook\学习\java\学习配图\G6~JT5@2)]Q6WB
3345(
W.png)
引用数据类型:
值传递的运用:**
package day09;
public class Circle {
double radius;
public double findArea() {
return Math.PI * radius * radius;
}
}
package day09;
//值传递的运用
public class PassObject {
public static void main(String[] args) {
PassObject object = new PassObject();
Circle c = new Circle();
object.printAreas(c, 5);
System.out.println("now radius is " + c.radius);
}
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(c.radius + "\t\t\t" + c.findArea());
}
c.radius = time + 1;
}
}
3.4递归方法
略
4、面向对象特征之一:封装性
4.1封装的含义
为什么需要封装?封装的作用和含义?
-
我要用洗衣机,只需要按一下开关和洗涤模式就可以了。有必要了解洗衣机内部的结构吗?有必要碰电动机吗?
-
我们程序设计追求“高内聚,低耦合”。
高内聚 :类的内部数据操作细节自己完成,不允许外部干涉;低耦合 :仅对外暴露少量的方法用于使用。
- 隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。通俗的说,把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想。
总结:封装属性的方法是为了信息的安全性,防止客户乱用。比如封装属性legs,如果用户使legs=-11,不切实际。而我们如果把legs封装起来,在方法中对legs设权限(例如:legs>0&&legs<3),而客户只能通过调用此方法才能使用legs,就不会造成乱用
4.2封装性思想具体的代码体现:
- 将类属性私有化,同时,提供公共的(public)方法来获取(getXxx)和设置(setXxx)此属性的值
- 不对外暴露的私有化方法
- 单例模式(将构造器私有化)。通俗来说,就是只能在类的内部造一个对象,不能在外面调用构造器造对象
- 不希望类在包外被调用,可以将类设置为缺省的
4.2Java规定的四种权限修饰符
修饰符 | 类内部 | 同一个包 | 不同包的子类 | 同一个工程 |
---|---|---|---|---|
private | Yes | |||
(缺省) | Yes | Yes | ||
protected | Yes | Yes | Yes | |
public | Yes | Yes | Yes | Yes |
==注意:==对于class的权限修饰只可以用public和default(缺省)
5、类的结构之三:构造器
5.1作用:
- 创建对象;Order o = new Order();
- 给对象进行初始化;Person p = new Person(“Peter”,15);
5.2语法格式:
public class Animal {
private int legs;
// 构造器:
//修饰符 类名 (参数列表) {
//初始化语句;
//}
public Animal() {
legs = 4;
}
public void setLegs(int i) {
legs = i;
}
public int getLegs() {
return legs;
}
}
5.3五条说明:
- 一个类可以创建多构造器,彼此构成重载
- 父类的构造器不可被子类继承
- 默认构造器的修饰符与所属类的修饰符一致
- 如果没显示的定义类的构造器的话,则系统默认提供一个空参的构造器。(因为类造对象必须调用构造器)
- 一个类中,至少会有一个构造器
5.4总结: 赋值的先后顺序
① 默认初始化
② 显式初始化
③ 构造器中初始化
④ 通过“对象.属性“或“对象.方法”的方式赋值
赋值的先后顺序:
① - ② - ③ - ④
5.6JavaBean概念
JavaBean是一种Java语言写成的可重用组件。
所谓javaBean,是指符合如下标准的Java类:
- 类是公共的
- 有一个无参的公共的构造器
- 有属性,且有对应的get、set方法
6、关键字:this
6.1理解this
- 它在方法内部使用,即这个方法所属对象的引用
- 它在构造器内部使用,表示该构造器正在初始化的对象。
- this 可以调用类的属性、方法和构造器
什么时候使用this关键字呢?
当在方法内需要用到调用该方法的对象时,就用this。具体的:我们可以用this来区分属性和局部变量。
比如:this.name = name;
6.2使用this,调用属性、方法
-
在任意方法或构造器内,如果使用当前类的成员变量或成员方法可以在其前面添加this,增强程序的阅读性。不过,通常我们都习惯省略this。
-
当形参与成员变量同名时,如果在方法内或构造器内需要使用成员变量,必须添加this来表明该变量是类的成员变量
-
使用this访问属性和方法时,如果在本类中未找到,会从父类中查找
6.3注意:
- "this(形参列表)"必须声明在类的构造器的首行!
- 在类的一个构造器中,最多只能声明一个"this(形参列表)"
- 可以在类的构造器中使用"this(形参列表)"的方式,调用本类中重载的其
他的构造器! - 明确:构造器中不能通过"this(形参列表)"的方式调用自身构造器
7、关键字:pachage/import
7.1JDK中主要的包介绍
- java.lang----包含一些Java语言的核心类,如String、Math、Integer、 System和
Thread,提供常用功能 - java.net----包含执行与网络相关的操作的类和接口。
- java.io ----包含能提供多种输入/输出功能的类。
- java.util----包含一些实用工具类,如定义系统特性、接口的集合框架类、使用与日
期日历相关的函数。 - java.text----包含了一些java格式化相关的类
- java.sql----包含了java进行JDBC数据库编程的相关类/接口
- java.awt----包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这
些类被用来构建和管理应用程序的图形用户界面(GUI)。
7.2import
格式:import 包名. 类名;
注意:
- 在源文件中使用import显式的导入指定包下的类或接口
- 声明在包的声明和类的声明之间。
- 如果需要导入多个类或接口,那么就并列显式多个import语句即可
- 举例:可以使用java.util.*的方式,一次性导入util包下所有的类或接口。
- 如果导入的类或接口是java.lang包下的,或者是当前包下的,则可以省略此import语句。
- 如果在代码中使用不同包下的同名的类。那么就需要使用类的全类名的方式指明调用的
是哪个类。 - 如果已经导入java.a包下的类。那么如果需要使用a包的子包下的类的话,仍然需要导入。
- import static组合的使用:调用指定类或接口下的静态的属性或方法
// 全类名方式
com.atguigu.exer3.Account acc1 = new com.atguigu.exer3.Account(1, 131, 12);
- java.sql----包含了java进行JDBC数据库编程的相关类/接口
- java.awt----包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这
些类被用来构建和管理应用程序的图形用户界面(GUI)。
7.2import
格式:import 包名. 类名;
注意:
- 在源文件中使用import显式的导入指定包下的类或接口
- 声明在包的声明和类的声明之间。
- 如果需要导入多个类或接口,那么就并列显式多个import语句即可
- 举例:可以使用java.util.*的方式,一次性导入util包下所有的类或接口。
- 如果导入的类或接口是java.lang包下的,或者是当前包下的,则可以省略此import语句。
- 如果在代码中使用不同包下的同名的类。那么就需要使用类的全类名的方式指明调用的
是哪个类。 - 如果已经导入java.a包下的类。那么如果需要使用a包的子包下的类的话,仍然需要导入。
- import static组合的使用:调用指定类或接口下的静态的属性或方法
// 全类名方式
com.atguigu.exer3.Account acc1 = new com.atguigu.exer3.Account(1, 131, 12);