面对对象小结
Java中标识符的命名规则
标识符
类名、方法名、变量名统称为标识符
标识符命名规范
帕斯卡命名法
所有单词首字母大写
如StudentInfomation、Employee、ClassName
驼峰命名法
第一个单词首字母小写,其余单词首字母大写
如studentInfomation、employee、className
类名使用帕斯卡命名法
方法名、变量名使用驼峰命名法
变量命名的要求
-
使用字母、数字、下划线或$符号组成
-
不能使用数字开头
-
不能使用关键字
-
见名知意
方法
方法是定义在类中的一段独立代码,能完成某个事情。
定义方法时,提供方法的名称、返回值类型、参数列表,这三点称为方法三要素,定义的方法都需要这
三部分。
当再使用该方法中的代码时,只需通过该方法名调用即可。
方法能够减少代码冗余。
1.通过类名调用
Math类
Math类是Java中的工具类,用于数学计算。
该类中的方法和属性都使用static修饰的,可以直接通过类名调用。
在任何类中,通过快捷键alt+7,展示方法列表
//常用方法和属性
System.out.println(Math.PI);//圆周率
System.out.println(Math.E);//自然常数
System.out.println(Math.abs(-5));//绝对值
System.out.println(Math.max(1,2));//最大值
System.out.println(Math.min(2.5,3.2));//最小值
System.out.println(Math.ceil(2.1));//3 向上取整
System.out.println(Math.floor(3.9));//3 向下取整
System.out.println(Math.round(-1.5));//-1 四舍五入
System.out.println(Math.random());//[0,1)直接的随机数
System.out.println(Math.sqrt(9));//3 平方根
System.out.println(Math.cbrt(27));//3 开立方
System.out.println(Math.pow(2,3));//8 2的3次幂
2.通过对象调用
创建对象: 类名 对象名 = new 类名([参数]);
Scanner sc = new Scanner(System.in);
sc.方法名();
Random rd = new Random();
rd.方法名();
3.在同一个类中,方法A直接调用方法B
class Test{
void funA(){
funB();
}
void funB(){
System.out.println("我是B方法");
}
}
自定义方法
方法的三要素:
-
方法名
- 使用驼峰命名法
-
方法返回值类型
-
如果有返回值,使用Java中的任意数据类型,方法体中使用return关键字返回对应类型的数据
-
如果没有返回值,使用void关键字
-
-
方法参数列表
- 参数写法:数据类型 形参名,数据类型 形参名
[修饰符] 返回值类型 方法名(参数列表){
方法体;
}
方法的类型
-
无参数无返回值
-
无参数有返回值
-
有参数无返回值
-
有参数有返回值
注意
-
有返回值的方法,必须要在方法体中加入return并能够执行,同时要return一个该方法返回值类型对应的数据。
-
没有返回值的方法,可以不用加入return关键字。如果加入return关键字,不能跟上数据。
-
方法中出现return,会立即结束方法。所以return语句之后不能再有代码。
-
定义方法时的参数称为形式参数,简称形参;调用方法时,实际传递的参数称为实际参数,简称实参。实参只需保证数据类型和形参相同即可。
面向对象综合练习–简易xxx管理
功能:
实现对图书的添加、修改、删除、查询功能
-
如何保存多个图书?
采用图书数组保存
-
如何实现添加?
判断数组是否有空元素(元素==null),如果有,将参数对象保存
- 如何实现删除?
遍历数组,根据参数编号循环比较,如果满足相等,用null覆盖
-
如何实现查询?
- 查询所有
遍历数组,空元素无需打印
-
查询单个
- 根据编号与数组中的元素遍历比较,满足时返回对应的对象
-
如何实现修改?
调用查询单个的方法,得到编号对应的对象,使用set方法对某个属性赋值
图书类Book
package com.ydh.tset;
public class Demo {
/*
* 图书类
* 编号
* 书名
* 作者
* 类型
* 出版社
* 价格
*
* 定义私有属性
* 自动生成全参构造方法、无参构造方法、getter/setter、toString()
* */
public class Book {
private int id;
//封装属性
private String name;
private String author;
private String type;
private String publisher;
private double price;
//用于输出对象时自动调用
@Override
public String toString() {
return "Book{" +
"id=" + id +
", name='" + name + '\'' +
", author='" + author + '\'' +
", type='" + type + '\'' +
", publisher='" + publisher + '\'' +
", price=" + price +
'}';
}
//封装:getter/setter
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getPublisher() {
return publisher;
}
public void setPublisher(String publisher) {
this.publisher = publisher;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
//无参数的构造方法
public Book() {
}
//全部参数的构造方法
public Book(int id, String name, String author, String type, String
publisher, double price) {
this.id = id;
this.name = name;
this.author = author;
this.type = type;
this.publisher = publisher;
this.price = price;
}
}
}
管理员类Manager
/*
* 图书管理员类
* 属性
* 保存图书的容器
*
*
* 方法
* 增 添加图书
* 删 删除图书
* 改 修改图书
* 查 查看图书
*
* */
public class Manager {
//保存图书对象的容器,该属性只能当前类使用,使用private修饰,不提供get/set
private Book[] bookList = new Book[10];
//添加
void addBook(Book book) {
for (int i = 0; i < bookList.length; i++) {
//如果存在空位,将参数保存在该位置上
if (bookList[i] == null) {
bookList[i] = book;
//停止循环,防止装满
break;
}
}
}
//查看所有图书
void showAll() {
System.out.println("编号\t书名");
for (Book book : bookList) {
if (book != null) {
//只显示编号和书名
System.out.println(book.getId()+"\t"+book.getName());
}
}
}
/*
* 根据id修改价格
* */
void update(int id,double newPrice){
//根据id得到对应的图书
//调用当前类中定义的根据id查询Book对象的方法
Book book = getBookById(id);
//判断是否得到
if(book!=null){
book.setPrice(newPrice);
}else{
System.out.println("图书不存在");
}
}
/*
* 根据图书编号删除
* */
void delete(int id) {
//遍历数组
for (int i = 0; i < bookList.length; i++) {
//bookList[i]是数组中的某个book对象
//如果该对象不为空,获取其id与参数判断
if(bookList[i]!=null && bookList[i].getId()==id){
//使用null覆盖,实现删除
bookList[i]=null;
break;
}
}
}
/*
* 根据id得到对应的图书对象
* */
Book getBookById(int id) {
//遍历当前所有的图书对象
for (Book book :bookList) {
//如果遍历出的对象不为空,得到对应的id与参数判断
if (book!=null && book.getId()==id) {
//返回对应的图书
return book;
}
}
//如果遍历未发现满足条件,返回null
return null;
}
}
程序入口类Main
import java.util.Random;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//创建管理员对象
Manager manager = new Manager();
while (true) {
System.out.println("请选择功能:1.添加图书\t2.修改图书\t3.删除图书\t4.查看所
有图书\t5.查看图书详情\t6.退出");
switch (sc.nextInt()) {
case 1:
int id = new Random().nextInt(9000) + 1000;
System.out.println("请输入书名");
String name = sc.next();
System.out.println("请输入作者");
String author = sc.next();
System.out.println("请输入类型");
String type = sc.next();
System.out.println("请输入出版社");
String publisher = sc.next();
System.out.println("请输入价格");
double price = sc.nextDouble();
//创建一个图书对象
Book book = new Book(id, name, author, type, publisher,
price);
//调用添加方法
manager.addBook(book);
break;
case 2:
System.out.println("请输入要修改的编号");
int updateId = sc.nextInt();
System.out.println("请输入要修改的价格");
double newPrice = sc.nextDouble();
manager.update(updateId, newPrice);
break;
case 3:
System.out.println("请输入要删除的编号");
manager.delete(sc.nextInt());
break;
case 4:
manager.showAll();
break;
case 5:
System.out.println("请输入要查看的编号");
System.out.println(manager.getBookById(sc.nextInt()));
break;
case 6:
System.exit(0);
break;
}
面对对象总结
可变参数
当某个方法的参数是同一种类型且数量未知时,参数列表中可以使用可变参数定义。
修饰符 返回值类型 方法名(数据类型... 形参名){
//这时的参数的数量是可变的,[0,∞)
//整个参数是一个数组
}
特点
-
可变参数只能出现一次,且是最后一个参数
-
可变参数实际是一个数组
-
调用参数为可变参数的方法时,传递的实参要使用逗号隔开
public class Main {
/*
* 计算一些数字的总和
* */
public int getSum(int... nums) {
int sum = 0;
for (int num : nums) {
sum += num;
}
return sum;
}
public static void main(String[] args) {
//
Main main = new Main();
//调用可变参数的方法,实参之间使用逗号隔开
System.out.println(main.getSum(1,2,3,4));
}
}
枚举
Java中的枚举是一个特殊的类,是一些常量的集合。
定义枚举类型
public enum 枚举类型名{
常量1,常量2...常量N
}
使用枚举类型
枚举类型名.常量名;
/*
* 定义枚举类型
* 使用enum关键字替换class
* 枚举是一个特殊的"类",
* 将某个事物使用指定的内容进行一一例举
* */
public enum Week {
//定义一组枚举类型的常量集合
SUN,MON,TUE,WED,THU,FRI,SAT
}
package test1;
public class Main {
public static void main(String[] args) {
//遍历自定义的枚举类型
//for (Week value : Week.values()) {
// System.out.println(value);
//}
System.out.println("请输入星期的简写");
Scanner sc = new Scanner(System.in);
String input = sc.next();
//根据字符串获取对应的枚举数据
Week week = Week.valueOf(input);
//判断枚举类型
switch (week) {
case SUN:
System.out.println("星期天");
break;
case MON:
System.out.println("星期一");
break;
case TUE:
System.out.println("星期二");
break;
case WED:
System.out.println("星期三");
break;
case THU:
System.out.println("星期四");
break;
case FRI:
System.out.println("星期五");
break;
case SAT:
System.out.println("星期六");
break;
default:
System.out.println("单词有误");
}
}
}
面向过程和面向对象编程思想
面向过程POP:所有步骤按顺序执行,注重执行的细节。
面向对象OOP:创建解决问题的对象,让各个对象调用各自的方法而配合完成。
在面向对象编程OOP中,给类中定义的方法,具体的实现过程,其实也是面向过程的。
对象和类
对象Object
某个类的具体实例
类Class
是拥有相同属性和行为的对象的集合。是对象的模板。
定义类
修饰符 class 类名{
//属性:定义变量
//行为:定义方法
}
类中的属性
-
成员变量、局部变量、静态常量
-
成员变量:定义在类中的变量,即类的属性。它有默认值。通过对象访问。
-
局部变量:定义在方法中的变量。它没有默认值。只能在方法中赋值后才能使用。
-
静态常量:特殊的成员变量,用final static修饰。它有默认值。通过类名访问。
类中的方法
-
构造方法
-
成员方法
-
静态方法
class Person{
//成员变量
String name;
//静态常量
final static String COUNTRY="中国";
//构造方法
public Person(String name){
this.name=name;
}
//成员方法
void info(){
//局部变量
String address="悉尼";
System.out.println("我叫"+name+",来自于"+COUNTRY+",现居住"+address);
}
//静态方法
public static void fun(){
}
}
创建对象
类名 变量名 = new 构造方法([参数]);
构造方法
是一种特殊的方法。方法名和类名一致,没有返回值部分。
访问修饰符 类名(数据类型 参数名称){
}
-
没有返回值部分,方法名必须和类名一致。
-
在使用new关键字创建对象时,调用对应的构造方法。
-
每个类在定义后,都隐藏有一个无参的构造方法。
-
如果自定义了有参数的构造方法,无参数的构造方法就会失效。如果想要使用无参构造方法,就要再写出来
-
构造方法通常用于限制创建对象时携带的参数,初始化成员变量。
-
构造方法之间都是重载关系,构造方法不能重写。
-
构造方法执行时,不一定会创建对象。如抽象类中有构造方法,但无法创建抽象类对象,只能在创建抽象类的子类对象时,自动调用抽象类的构造方法。
面向对象三大特性
封装
将类中的属性使用private修饰,这样就能防止非当前类对其访问,隐藏类中的关键属性。
通常会对private修饰的属性提供公开的get和set方法用于获取和赋值。
继承
-
类A extend 类B。
-
接口A extends 接口B。
前者就是后者的子类,前者的对象就能直接访问后者中非私有成员。
重写Override
子类继承父类后,对父类中的非私有方法进行重写,达到拓展或重做的目的
-
必须满足方法名、返回值、参数列表都相同
-
访问权限不能比父类中的方法更严格
-
不能抛出比父类中的方法更大的异常
重载Overload
在一个类中,某个方法在不同的参数下,表现不同的行为。同名不同参。
-
方法名必须相同
-
参数列表必须不同(类型和数量)
-
无返回值无关
this和super
都可以当做对象后构造方法使用。
-
当做对象:this表示当前类的对象,super当前类的父类对象。
this或super当做对象使用时,只能用在非静态方法中。
-
当做构造方法
-
this()表示当前类中无参构造方法,如果带参数就表示对应参数的构造方法
-
super()表示当前类的父类的无参构造方法,如果带参数就表示对应参数的构造方法
-
this()或super()只能用在另一个构造方法的首行。
在继承后,如果子类和父类都没有写出任何构造方法时,子类中有一个隐藏的无参构造方法,会自动调用父类的无参构造方法
public class Father{
}
public class Son extends Father{
/*
会有这段代码
*/
public Son(){
super();
}
}
所以如果在父类中定义了有参数的构造方法,无参构造方法就会失效,子类必须调用父类中的有参数的构造方法
public class Father{
String name;
public Father(String name){
this.name=name;
}
}
public class Son extends Father{
/*
必须要调用super(String name)
*/
public Son(String name){
super(name);
}
}
Object类
是所有类的父类。任何类都间距地继承了Obejct类。所以所有类都能访问Object类中的方法,都可以进行重写。
-
toString()是Object类中的一个方法,在输出对象时自动调用。
默认输出"类全限定名@十六进制哈希码"。通常在自定义的实体类中,重写toString(),输出当前类的属性。
-
equals()是Object类中的一个方法,用于比较两个对象是否相同。
默认使用==比较内存地址。通常在自定义的实体类中,重写equals(),自定义比较的规则。
-
hashCode()是Object类中的一个方法,用于获取对象的哈希码。
默认使用全部参数生成哈希码。可以重写自定义生成哈希码的参数。
对象转型
类似于原始类型间的数据类型转换
-
向上转型:父类变量 = 子类对象;
类似于自动类型转换
Person p = new Person();
Object obj = p;
-
向下转型: 子类变量 =(子类) 父类对象;
类似于强制类型转换
Animal anl = new Animal();
Cat c = (Cat) anl;
多态
在继承关系中,子类的对象可以保存到父类的变量中。(向上转型)
多态常用与定义方法时,形参为一个父类或接口类型变量,实参为子类对象。
无法通过父类变量调用子类中独有的方法。如果调用重写了父类中的方法时,执行重写后的内容。
父类/父接口 对象 = new 子类();
public class Father{
public void smoking(){
System.out.println("Father is smoking");
}
}
public class Son extends Father{
public void play(){
System.out.println("Son is playing");
}
public void smoking(){
System.out.println("Son is smoking");
}
}
public class Test{
public static void main(String[] args){
Father father = new Son();
//可以访问
father.smoking();//输出Son is smoking
//无法访问
//father.play();
}
}
修饰符
访问修饰符
当前类 | 当前包 | 不同包中的子类 | 不同包中的非子类(同一个项目中的不同类) | |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
不写 | √ | √ | × | × |
private | √ | × | × | × |
final
-
修饰属性
- 变量变为常量,定义时就要赋值,程序运行过程中不能改变其值。
-
修饰方法
- 方法成为最终方法,不能重写。
-
修饰类
- 类为最终类,不能被继承。
abstract
-
修饰方法
- 方法为抽象方法,没有方法体。同时所在的类也需要使用abstract定义为抽象类修饰类
-
抽象类不能创建对象
-
抽象类除了能定义抽象方法外,其余与普通类无区别
-
抽象类中可以有构造方法,在创建其子类对象时自动调用
-
抽象类通常需要被继承,一旦有子类继承,子类就要重写抽象父类中的所有抽象方法,或者子类也是一个抽象类
-
interface
用于定义接口的关键字。代替class,能让java实现"多继承"。
如果某个抽象类中的所有方法都是抽象方法时,可以将该类改为接口。
abstract class --> interface
-
接口是一个完全抽象类,其中的方法都是public abstract修饰的抽象方法,其中的属性都是public
-
final static修饰的静态常量。
-
接口中没有构造方法,不能创建对象
-
接口通过implements“继承”。类A implements 接口A,接口B,称为类A实现了接口A和接口B,一个类可以"继承"多个父接口
-
一个类一旦实现了某个接口,就要重写其中的所有抽象方法
-
JDK1.8后,可以在接口中定义default或static修饰的方法,该方法不用重写。
static
被static修饰的内容称为静态成员
静态成员在类加载时就会保存到内存中,所以访问时通过类名直接访问。
当某个属性或方法被高度重用时,将其定义为静态的,之后通过类名方便调用。
-
修饰方法
public static void fun(){ }
-
修饰属性
public static final int NUM=123;
-
定义代码块
static{ //在调用该类中的方法或创建对象时自动执行一次 }