Java---第五章
- 一 类和对象
- 类的由来:
- 二者之间的关系
- this关键字:
- 构造方法
- 二 方法带参
- 构造方法带参:
- 方法带参
- 对象数组
- 引用数据类型作为方法参数
- 方法重载
- 面向对象说明
- 面向对象和面向过程的区别
一 类和对象
类的由来:
人们在日常生活中,经常会讲具有相同特征或者具有相同的行为的事物归为一类。
在Java中,用来描述这类事物的就是Java类,Java类就是这样诞生的,Java是一门以类为组织单元的语言
我们定义的Java类就是一种Java数据类型,该类型属于引用数据类型。
如何定义类:
public class 类名{
}
例如:
定义一个人
找出人类共同的特征:
public class Person{
public String name;//姓名
public String sex;//性别
public int age;//年龄
}
找出人类共同的行为:
在Java中用方法描述行为,方法的定义语法如下:
//[]中内容表示可有可无
访问修饰符 返回值类型 方法名([参数列表]){
[return 返回值;]
}
示例:
public class Person{
public String name;//姓名
public String sex;//性别
public int age;//年龄
public void eat(){
System.out.println("吃饭");
}
public void sleep(){
System.out.println("睡觉");
}
public void work(){
System.out.println("工作");
}
}
案例1:
定义一个计算器,计算器能够对两个数字进行加减乘除
分析:
- 计算器可以接收两个数字和一个运算符
- 计算器能够进行计算
public class Caculator{
public double number1;//接收数字1
public double number2;//接收数字2
public String operator;//接收运算符
public void caculator(){//计算
switch (operator){
case "+":
System.out.println(number1 + number2);
break;
case "-":
System.out.println(number1 - number2);
break;
case "*":
System.out.println(number1 * number2);
break;
case "/":
System.out.println(number1 / number2);
break;
}
}
}
类图:
类图是描述类的结构,与流程图一样,简单直观
- public修饰的属性和方法前要使用“+”
- private修饰的属性和方法前要使用“-”
二者之间的关系
类是描述多个事物共有特征和行为的一个抽象体
对象是一个具体的事务,每一个属性和行为都是具体的
类是对象的集合体,类是用来构建具体的对象的
语法:
类名 对象名 = new 类名();
对象名.属性名 = 属性值;
public class study {
public static void main(String[] args) {
//这里p称为对象名,和数组名一样,本质都是变量
Person p = new Person();//构建了一个具体的人
p.name = "汴京城下君";
p.sex = "男";
p.age = 20;
}
}
成员变量:
在类中定义的变量就是成员变量。
成员变量的初始值:
类型 | 初始值 |
---|---|
引用数据类型 | null |
整数 | 0 |
浮点数 | 0.0 |
boolean | false |
char | ‘\u0000’ |
局部变量:
在方法内部定义的变量。没有初始值,所以使用前要初始化
public void eat(){
String name;//报错,没有初始化
System.out.println(name+"吃饭");
}
当局部变量与成员变量重名时,局部变量的优先级更高。
public class Person{
public String name;//姓名
public String sex;//性别
public int age;//年龄
public void eat(){
String name="张三";
System.out.println(name+"吃饭");
}
public void sleep(){
System.out.println("睡觉");
}
public void work(){
System.out.println("工作");
}
}
public class ob {
public static void main(String[] args) {
//这里p称为对象名,和数组名一样,本质都是变量
Person p = new Person();//构建了一个具体的人
p.name = "汴京城下君";
p.sex = "男";
p.age = 20;
p.eat();
}
}
输出:
张三吃饭
this关键字:
在方法中,如果局部变量和成员变量同名,此时又想使用成员变量,怎么办呢?
public class Person{
public String name;//姓名
public String sex;//性别
public int age;//年龄
public void eat(){
String name="张三";
System.out.println(this.name+"吃饭");
}
}
public class ob {
public static void main(String[] args) {
//这里p称为对象名,和数组名一样,本质都是变量
Person p = new Person();//构建了一个具体的人
p.name = "汴京城下君";
p.sex = "男";
p.age = 20;
p.eat();
}
}
输出:
汴京城下君吃饭
this还可以调用成员的方法:
public class Person{
public String name;//姓名
public String sex;//性别
public int age;//年龄
public void eat(){
String name="张三";
System.out.println(name+"吃饭");
sleep();
// 也相当于this.sleep();
}
public void sleep(){
System.out.println("睡觉");
work();
}
public void work(){
System.out.println("工作");
eat();
}
}
构造方法
主要用于创建对象以及完成对象的属性初始化操作,构造方法不能被对象调用
语法:
//[]中内容可有可无
访问修饰符 类名([参数列表]){
}
示例:
public class Person{
public String name;//姓名
public String sex;//性别
public int age;//年龄
public Person(){
this.name = "默认姓名";
this.sex = "默认性别:男";
this.age = 21;
}
public void eat(){
String name="hello";
System.out.println(age+"岁的"+sex+"性"+this.name+"吃饭");
}
}
public class ob {
public static void main(String[] args) {
//这里p称为对象名,和数组名一样,本质都是变量
Person p = new Person();//构建了一个具体的人
p.eat();
p.name = "汴京城下君";
p.sex = "男";
p.age = 20;
p.eat();
}
}
输出:
21岁的默认性别:男性默认姓名吃饭
20岁的男性汴京城下君吃饭
二 方法带参
构造方法带参:
观察以下代码,有什么问题?
现有计算机类定义如下:
public class Computer{
public String brand;//品牌
public String type;//型号
public int price;//价格
}
现要创建三个具体的计算机实例,如下:
public class ComputerTest{
public static void main(String[] args){
Computer c1 = new Computer();
c1.brand = "联想";
c1.type = "w1";
c1.price = 5500;
Computer c2 = new Computer();
c2.brand = "联想";
c2.type = "w2";
c2.price = 6500;
Computer c3 = new Computer();
c3.brand = "联想";
c3.type = "w3";
c3.price = 7500;
}
}
分析问题:
每创建一个对象,都会出现重复的对象的属性赋值,这样造成了大量的冗余代码
可以使用带参构造方法来优化
构造方法带参语法:/font>
访问修饰符 类名(数据类型1 变量1,数据类型2 变量2,.....数据类型n 变量n){
}
优化后:
带参构造方法
public class Computer{
public String brand;//品牌
public String type;//型号
public int price;//价格
public Computer(){}
//如果在一个类中已经定义了带参数的构造方法,此时还想用无参构造方法,
//那必须将无参构造方法也定义出来
public Computer(String brand,String type,int price){
//此时在类中定义了带参数的构造方法,那么编译器不会为这个类添加默认的无参构造方法
}
}
构造新对象
public class ComputerTest{
public static void main(String[] args){
Computer c1 = new Computer("联想","w1",5500);
Computer c2 = new Computer("联想","w2",6500);
Computer c3 = new Computer("联想","w3",7500);
}
}
案例1:
定义书籍类(名称,出版社,出版年月,价格)并用带参构造方法创建对象
public class Book{
public String name;//书名
public String publisher;//出版社
public String publishtime;//出版时间
public double price;//价格
public Book(){}
public Book(String name,String publisher,String publishtime, double price){
}
}
public class BookTest{
public static void main(String[] args){
Book b1 = new Book("活着","北京十月文艺出版社","2017-06-01",32.5);
Book b2 = new Book("动物农场","上海译文出版社","2010-08-01",28.4);
Book b3 = new Book("瓦尔登湖","北京十月文艺出版社","2019-01-01",25.8);
Book b4 = new Book("你当像鸟飞往你的山","南海出版公司","2019-11-01",34.2);
}
}
方法带参
方法带参语法:
访问修饰符 返回值类型 方法名(数据类型1 变量名1,...数据类型n 变量名n{
[return 返回值;]
}
//带参方法调用
对象名.方法名(实参1,实参2,...实参n);
案例1:
计算器
public class Calculator{
public int number1;
public int number2;
public String operator;
public int calculator(){
//如果在一个方法中返回值类型不是void,那么在选择结构中,
//必须每种情况都提供一个返回值
switch (operator) {
case "+": return number1 + number2;
case "-": return number1 - number2;
case "*": return number1 * number2;
case "/": return number1 / number2;
default:return 0;
}
}
}
案例2:
某商家共有30件啤酒,每件价格是72元,商家在3天内卖完这30件,请问每天买了多少钱?(利用上面计算器)
public class CalculatorTest{
public static void main(String[] args){
Calculator c = new Calculator();
c.number1 = 30;
c.number2 = 72;
c.operator = "*";
int total = c.calculator();
c.number1 = total;
c.number2 = 3;
c.operator = "/";
int avg = c.calculator();
System.out.println("每天买了"+avg);
}
}
存在什么问题?
依然是存在造成了大量的冗余代码
我们依然可以用带参构造方法进行代码优化,但是这样也是不符合生活的,
这里创建了两台计算器,生活中我们只需要一台即可。
利用带参方法进行优化:
public class Calculator{
public int calculator(int number1,int number2,String operator){
switch (operator) {
case "+": return number1 + number2;
case "-": return number1 - number2;
case "*": return number1 * number2;
case "/": return number1 / number2;
default:return 0;
}
}
}
public class CalculatorTest{
public static void main(String[] args){
Calculator c = new Calculator();
int total = c.calculator(30,72,"*");
int avg = c.calculator(total,3,"/");
System.out.println("每天买了"+avg);
}
}
案例3:
求各数的阶乘
public int factorial(int number){
if(number==0) {
return 1;
}
int result = 1;
for(int i=1;i<=number;i++){
result = result * i;
}
return result;
}
案例4:
使用一个方法判断这个数是否为素数
public class Number{
public boolean isPrime(int number){
if(number==2) return true;
for(int i=2;i*i<number;i++){
if(number%i==0){
return false;
}
}
return true;
}
}
public class NumberTest{
public static void main(String[] args){
Number tal = new Number();
boolean result = tal.isPrime(5);
System.out.println(result);
}
}
对象数组
例如存储学生信息:
public class Student{
public String name;
public int age;
public Student(String name,int age){
this.name = name;
this.age = age;
}
}
public class StudentTest{
public static void main(String[] args){
Student[] students = new Student[2];
students[0] = new Student("张三",21);
students[1] = new Student("李四",22);
}
}
案例1:
使用数组存储学生选择的5门必修课程(课程编号,课程名称,学分)
public class Coures{
public int code;
public String name;
public double scores;
public Coures(int code,String name,double scores){
this.code = code;
this.name = name;
this.scores = scores;
}
}
public class CouresTest{
public static void main(String[] args){
Coures[] lessons = new Coures[5];
lessons[0] = new Coures(31,"数据结构与算法",2);
lessons[1] = new Coures(1,"Java",1.5);
lessons[2] = new Coures(2,"C++",1.3);
lessons[3] = new Coures(12,"Python",2.1);
lessons[4] = new Coures(18,"MySQL",1.9);
}
}
引用数据类型作为方法参数
案例分析:
某手机专卖店有100个手机展架,售货员现在依次向展架上摆放手机。请使用面向对象的设计思想描述这一过。(手机有品牌,型号和价格)
分析:
- 这一过程涉及到的对象有两个,一个是手机,一个是售货员,因此我们需要为这两个对象构建类
- 摆放手机是售货员的一个行为,因此需要用到方法
- 100个手机展架都是摆放手机的,因此需要使用对象数组存储
代码:
public class Mobile {
public String brand;
public String type;
public double price;
public Mobile(String brand,String type,double price){
this.brand = brand;
this.type = type;
this.price = price;
}
}
public class Saler {
public Mobile[] mobiles = new Mobile[100];
public void playmobies(Mobile mobile){
for(int i=0;i<mobiles.length;i++){
if(mobiles[i]==null){
mobiles[i] = mobile;
break;
}
}
}
}
public class MobileTest{
public static void main(String[] args){
Saler saler = new Saler();
//调用售货员放手机
saler.playmobies(new Mobile("小米","小米13",3499));
}
}
案例1:
现有甲乙丙三个班级成绩统计如下:
- 甲:80,72,85,67,50,76,95,49
- 乙:77,90,92,89,67,94
- 丙:99,87,95,93,88,78,85
现要求将每个班的成绩从高到低依次排序
import java.util.Arrays;
public class TeacherTest{
public static void main(String[] args){
int[] arr1 = {80,72,85,67,50,76,95,49};
int[] arr2 = {77,90,92,89,67,94};
int[] arr3 = {99,87,95,93,88,78,85};
sortDesc(arr1);
System.out.println(Arrays.toString(arr1));
sortDesc(arr2);
System.out.println(Arrays.toString(arr2));
sortDesc(arr3);
System.out.println(Arrays.toString(arr3));
}
public static void sortDesc(int[] arr){
for(int i=0;i<arr.length;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;
}
}
}
}
}
基本数据类型传值时,传递的是值的拷贝
public class PassingValue{
public static void main(String[] args){
int a = 10;
change(a);
System.out.println(a);
}
public static void change(int number){
number++;
}
}
输出 :
10
引用数据类型传值时,传递的是对象在堆内存上的空间地址
方法重载
在同一个类中,方法名相同,参数列表不同的多个方法构成方法重载
示例:
public class Returnd{
public int sum(int x,int y){
return x+y;
}
public int sum(int x,int y,int c){
return x+y+c;
}
}
误区:
public class Teacher{
public int sum(){
return 1;
}
public void sum(){
System.out.println("1");
}
}
不是方法重载,因为方法名和参数列表都一样。
在同一个类中,不可能出现这种方法定义
面向对象说明
举例:
简易学生管理系统
- 该过程涉及到的对象(事务)有两个:用户和菜单
- 用户具有增删改查成绩的动作
面向对象和面向过程的区别
- 面向对象的侧重点在对象上,需要利用对象的行为来完成过程的组装
- 面向过程 的侧重点在过程的实现上