开篇
主线
-
类及类的成员
属性、方法、构造器;
代码块,内部类
-
面向对象三大特征
继承、封装、多态
-
其他关键字
this
,super
,static
,final
,abstract
,interface
等
面向对象的两个要素
一、是什么
类:对一类事物的描述,是抽象的、概念上的定义
对象:是实际存在的该类事物的每个个体,因而也称为实例(instance)
-
面向对象程序设计的重点是类的设计
-
设计类,就是设计类的成员。(这个设计是动词)
二、类和对象的使用(面向对象思想落地的实现):
- 创建类,设计类的成员
- 创建类的对象
- 通过
对象.属性
或对象.方法
调用对象的结构
三、如果创建了一个类的多个对象,则每个对象都独立的拥有一套类的属性。(非static的)
意味着:如果我们修改一个对象的属性a,则不影响另外一个对象属性a的值。
对象的内存解析
实践
public class PersonTest {
public static void main(String[] args) {
//2. 创建Person类的对象
Person p1 = new Person();
//和这个一样Scanner scanner = 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);//null
System.out.println(p2.isMale);
//*******************************
//将p1变量保存的对象地址值赋给p3,导致p1和p3指向了堆空间中的同一个对象实体。
Person p3 = p1;
System.out.println(p3.name);//Tom
p3.age = 10;
System.out.println(p1.age);//10
}
}
//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);
}
}
类的成员
属性
属性(成员变量) vs 局部变量
-
相同点:
- 定义变量的格式:数据类型 变量名 = 变量值
- 先声明,后使用
- 变量都有其对应的作用域
-
不同点:
-
在类中声明的位置的不同
属性:直接定义在类的一对{}
内
局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量 -
关于权限修饰符的不同
属性:可以在声明属性时,指明其权限,使用权限修饰符。
常用的权限修饰符:缺省(不写时默认)、private、public、protected —>详细在封装性中目前,大家声明属性时,都使用缺省就可以了。
局部变量:不可以使用权限修饰符。
-
默认初始化值的情况:
- 属性:类的属性,根据其类型,都有默认初始化值。
整型(byte、short、int、long):0
浮点型(float、double):0.0
字符型(char):0 (或’\u0000’)
布尔型(boolean):false
引用数据类型(类、数组、接口):null
- 局部变量:没有默认初始化值。
意味着,我们在调用局部变量之前,一定要显式赋值。
特别地:形参在调用时,我们赋值即可。
- 属性:类的属性,根据其类型,都有默认初始化值。
-
-
在内存中加载的位置:
属性:加载到堆空间中 (非static)
局部变量:加载到栈空间 -
总结
成员变量 | 局部变量 | |
---|---|---|
声明的位置 | 直接声明在类中 | 方法形参或内部、代码块内、构造器内等 |
修饰符 | private、public、static、final等 | 不能用权限修饰符修饰,可以用final修饰 |
初始化值 | 有默认初始化值 | 没有默认初始化值,必须显式赋值,方可使用 |
内存加载位置 | 堆空间 或 静态域内 | 栈空间 |
方法
方法的声明格式:
注意:static、final、abstract 来修饰的方法,后面再讲。
说明:
- 关于权限修饰符:默认方法的权限修饰符先都使用public
Java规定的4种权限修饰符:private、public、缺省、protected -->封装性再细说 - 返回值类型: 有返回值 vs 没有返回值
- 如果方法有返回值,则必须在方法声明时,指定返回值的类型。同时,方法中,需要使用return关键字来返回指定类型的变量或常量:“return 数据”。
- 如果方法没有返回值,则方法声明时,使用void来表示。通常,没有返回值的方法中,就不需要使用return.但是,如果使用的话,只能“return;”表示结束此方法的意思。
- 我们定义方法该不该有返回值?
① 题目要求
② 凭经验:具体问题具体分析
- 方法名:属于标识符,遵循标识符的规则和规范,“见名知意”
- 形参列表: 方法可以声明0个,1个,或多个形参。
- 格式:数据类型1 形参1,数据类型2 形参2,…
- 我们定义方法时,该不该定义形参?
① 题目要求
② 凭经验:具体问题具体分析
- 方法体:方法功能的体现。
return关键字的使用:
- 使用范围:使用在方法体中
- 作用:
① 结束方法
② 针对于有返回值类型的方法,使用"return 数据"方法返回所要的数据。 - 注意点:return关键字后面不可以声明执行语句。
递归调用
-
方法的使用中,可以调用当前类的属性或方法
特殊的:方法A中又调用了方法A:递归方法。
-
方法中,不可以定义方法。⭐
练习
- 利用面向对象的编程方法,设计类Circle计算圆的面积。
package com.atguigu.exer;
public class CircleTest {
public static void main(String[] args) {
Circle circle = new Circle();
circle.radius = 2;//半径
System.out.println(circle.findArea());
}
}
//圆
class Circle{
double radius;
public double findArea() {
return Math.PI * radius * radius;
}
}
- 编写程序,声明一个
printMatrix
方法,在方法中打印一个4行3列的*
型矩形,在main方法中调用该方法。
public class Exer3Test {
public static void main(String[] args) {
Exer3Test test = new Exer3Test();
test.printMatrix();
}
public void printMatrix() {
for (int i = 0; i < 4;i++){
for(int j = 0; j < 3;j++){
System.out.print("* ");
}
System.out.println();
}
}
}
- 修改上一个程序,在
printMatrix
方法中,除打印一个4行3列的*
型矩形外,再计算该矩形的面积,并将其作为方法返回值。在main方法中调用该方法,接收返回的面积值并打印。
public class Exer3Test {
public static void main(String[] args) {
Exer3Test test = new Exer3Test();
System.out.println("面积是:" + test.printMatrix());
}
public int printMatrix() {
for (int i = 0; i < 4;i++){
for(int j = 0; j < 3;j++){
System.out.print("* ");
}
System.out.println();
}
return 4 * 3;//返回矩形面积
}
}
- 修改上一个程序,在
printMatrix
方法提供row
和column
两个参数,方法中打印一个m*n
的*
型矩形,并计算该矩形的面积, 将其作为方法返回值。在main方法中调用该方法,接收返回的面积值并打印。
public class Exer3Test {
public static void main(String[] args) {
Exer3Test test = new Exer3Test();
System.out.println("面积是:" + test.printMatrix(4,3));
}
public int printMatrix(int row, int column) {
for (int i = 0; i < row;i++){
for(int j = 0; j < column;j++){
System.out.print("* ");
}
System.out.println();
}
return row * column;//返回矩形面积
}
}
- 对象数组题目:
定义类Student,包含三个属性:学号number(int),年级state(int),成绩score(int)。创建20个学生对象,学号为1到20,年级和成绩都由随机数确定。
-
问题一:打印出3年级(state值为3)的学生信息。
-
问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息
提示:
-
生成随机数:
Math.random()
,返回值类型double; -
四舍五入取整:
Math.round(double d)
,返回值类型long。
public class Exer3Test {
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 = (i+1);
stus[i].state = (int)(Math.random() * (6 - 1 + 1) + 1);
stus[i].score = (int)(Math.random() * (100 + 1));
}
//输出成绩:打印出3年级(state值为3)的学生信息
for (int i = 0; i < stus.length; i++) {
if (stus[i].state == 3) {
System.out.println(stus[i].showInfo());
}
}
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;
}
}
}
for (int i = 0; i < stus.length; i++) {
System.out.println(stus[i].showInfo());
}
}
}
/**
* Student
*/
class Student {
int number;
int state;
int score;
public String showInfo() {
return "学号:" + number + ",年级:" + state + ",成绩:" + score;
}
}
改进,将其中的方法进行封装。优雅!!!
public class Exer3Test {
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 = (i+1);
stus[i].state = (int)(Math.random() * (6 - 1 + 1) + 1);
stus[i].score = (int)(Math.random() * (100 + 1));
}
//输出成绩:打印出3年级(state值为3)的学生信息
Exer3Test test = new Exer3Test();
test.searchState(stus, 3);
System.out.println("---------------------------");
//使用冒泡排序按学生成绩排序,并遍历所有学生信息
test.bobuleSort(stus);
test.print(stus);
}
/**
* 查找指定年级的学生并输出
* @param stus 要查找的学生数组
* @param state 要查找的年级
*/
public void searchState(Student[] stus, int state){
for (int i = 0; i < stus.length; i++) {
if (stus[i].state == state) {
System.out.println(stus[i].showInfo());
}
}
}
/**
* 冒泡排序数组
* @param stus 要排序的数组
*/
public void bobuleSort(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;
}
}
}
}
/**
* 遍历输出数组
* @param stus 要遍历的数组
*/
public void print(Student[] stus){
for (int i = 0; i < stus.length; i++) {
System.out.println(stus[i].showInfo());
}
}
}
/**
* Student
*/
class Student {
int number;
int state;
int score;
public String showInfo() {
return "学号:" + number + ",年级:" + state + ",成绩:" + score;
}
}
-
声明一个日期类型
Date
:有属性:年year,月month,日day。 创建2个日期对象,分别赋值为:你的出生日期,你对象的出生日期, 并显示信息。“没有对象,我很抱歉。” --鲁迅
public class Exer3Test {
public static void main(String[] args) {
Date myDate = new Date();
Date exDate = new Date();
myDate.setDate(2000, 10, 26);
exDate.setDate(2000, 3, 11);
System.out.println("我的生日" + myDate.print());
System.out.println("前任生日" + exDate.print());
}
}
class Date {
int year;
int month;
int day;
public void setDate(int year,int month,int day){
this.year = year;
this.month = month;
this.day = day;
}
public String print() {
return ("生日为:" + year + "年"
+ month + "月" + day + "日。");
}
}