Java中标识符的命名规则

标识符

类名、方法名、变量名统称为标识符

标识符命名规范

帕斯卡命名法

所有单词首字母大写

如Employee、ClassName、StudentInfomation

驼峰命名法

第一个单词首字母小写,其余单词首字母大写

如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 类名([参数])

Scannersc=newScanner(System.in);
sc.方法名();Randomrd=newRandom();
rd.方法名();

3.在同一个类中,方法A直接调用方法B

class Test{void funA(){funB();}void funB(){System.out.println("我是B方法");}
}

方法调用总结

调用方式

  1. 通过类名调用

  1. 通过对象调用

  1. 直接调用

参数

  • 无参数

Scanner sc=new Scanner(System.in);
sc.next();//调用无参数方法
  • 有参数

Random rd=new Random();
rd.nextInt(10);//调用有参数方法

返回值

  • 没有返回值 方法名的前面用void表示

class Test{void funB(){System.out.println("我是B方法");}public static void main(String[] args){Test t=new Test();}
}
  • 有返回值

Random rd=new Random();
int num=rd.nextInt(10);

自定义方法

方法的三要素:

  • 方法名

使用驼峰命名法

  • 方法返回值类型

如果有返回值,使用Java中的任意数据类型,方法体中使用return关键字返回对应类型的数据

如果没有返回值,使用void关键字

  • 方法参数列表

参数写法: 数据类型 形参名.数据类型 形参名

[修饰符] 返回值类型 方法名(参数列表){方法体;
}

方法的类型

  • 无参数无返回值

void 方法名(){//方法体return;//遇到return立即结束方法
}
  • 无参数有返回值

int 方法名(){//方法体return;
}
  • 有参数无返回值

void 方法名(数据类型1 形参名1,数据类型2 形参名2){//方法体return;
}
  • 有参数有返回值

//生成a,b中包含最小值,不包含最大值范围内的随机数
double rand(int a,int b){double num=Math.floor(Math.random()*Math.abs(a-b)+Math.min(a,b))return num;
}

注意:

  1. 有返回值的方法,必须要在方法体中加入return并能够执行,同时要return一个该方法返回值类型对应的数据

  1. 没有返回值的方法,可以不用加入return关键字,如果加入return关键字,不能跟上数据

  1. 方法中出现return,会立即结束方法,所以return语句之后不能再有代码

  1. 定义方法时的参数称为形式参数,简称为形参。调用方法时,实际传递的参数称为实际参数,简称实参,实参只需保证数据类型和形参相同即可

编程思想

面向过程编程

Procedure Oriented Programming 简称为POP

是一种基本的编程思想,将一件事情按流程步骤执行,逻辑清晰

每一步都是基于上一步的流程去继续实现

注重于分析问题的步骤

如果逻辑复杂,如xxx管理系统,使用POP就会变得很麻烦

C语言就是一门面向过程的编程语言

面向对象编程

Object Oriented Programming 简称OOP

是一种编程思想,核心是创建解决问题的对象,赋予对象行为和特征,让这些对象互相配合执行

每个对象的行为实际也是面向过程的

注重于全局如何创建完成某件事情的对象,如何适时的调用

这种思想致力于将计算机中的世界,描述的和现实中一致的思想

如洗衣服

pop:得到衣服--->得到洗衣服--->洗--->晾晒

oop:得到衣服对象--->得到洗衣机对象--->调用洗衣机对象的洗衣服行为

总结:

  1. 面向过程:亲历亲为,侧重于分析完成事情的过程

  1. 面向对象:所有事情交给相应的对象完成,侧重于如何创建解决问题的对象

类和对象

类Class

具有相同属性和行为的对象的集合,相当于模板

  • 属性

描述这个类的特征值, 在程序中,通过定义变量实现

  • 行为

描述这个类的动作,在程序中,通过定义方法实现

创建一个Class文件,就是创建一个类

定义类

[修饰符] class 类名{

//属性(定义变量)

//行为(定义方法)

}

/*
*定义车的模板
*属性:变量
*  品牌
*  颜色
*  座位数
*  排量
*  ....
*
*行为:方法
*  跑
*  说话
*  飞
* ....
*/
public class Car(){//定义变量  数据类型 变量名:String brand;String color;int seat;//定义方法void run(){System.out.println("车在跑。。")}void introduce(){//在方法中可以直接访问同一个类中的属性System.out.println("我是一辆"+brand+"牌的"+color+"色的"+seat+"座车")}
}

对象 Object

对象由某个类创建出来的具体实例

创建对象

类名 对象名=new 构造方法([参数])

创建出的对象,通过"."操作符访问类中的非私有属性和方法

public class Test4 {public static void main(String[] args) {// 创建Car类的对象//类名 对象名 = new 类名();Car benz = new Car();//对象.类中的属性和方法benz.seat = 5;benz.color="白";benz.brand="奔驰";benz.introduce();benz.run();}
}

类和对象的关系

对象是类的具体表现,类是对象的模板

如制作月饼的模具就是一个类,每次用这个模具创建出来的月饼就是一个对象

先定义类,才能通过该类获取对象

作业:模拟电子宠物

public class Pet {//定义属性String type;String nickName;String birthday;//定义行为void eat(String food) {System.out.println( nickName+ "开始吃"+food);}void toy(String toy) {System.out.println(nickName + "开心的玩"+toy);}void sing(){System.out.println("我是一只鹦鹉,我叫hah,hhhh~~~~");}
}
//宠物机
//属性
//  宠物
//方法
//  主界面import java.util.Scanner;public class Pet_machine {Scanner sc = new Scanner(System.in);void createPet(){System.out.println("-------------");Pet pet = new Pet();//创建一个宠物对象//定义方法中的变量,称为局部变量,必须先赋值再使用String type="猫咪";System.out.println("请选择宠物类型:");System.out.println("1.猫咪");System.out.println("2.小狗");System.out.println("3.鹦鹉");int in=sc.nextInt();switch (in){case 1:break;case 2:type = "小狗";break;case 3:type = "鹦鹉";break;default:System.out.println("输入有误");}pet.type=type;System.out.println("请输入宠物昵称:");pet.nickName=sc.next();System.out.println("请输入宠物生日:");pet.birthday=sc.next();System.out.println("宠物已生成!");int input=0;while (true){System.out.println("请选择功能:1.喂食 2.玩耍 3.唱歌 4.退出");input=sc.nextInt();switch (input){case 1:System.out.println("请输入食物:");String food=sc.next();pet.eat(food);break;case 2:System.out.println("请输入玩具:");String toy=sc.next();pet.toy(toy);break;case 3:pet.sing();break;}if(input==4){break;}}}
}
public class Test1 {public static void main(String[] args) {Pet_machine z=new Pet_machine();z.createPet();}
}

成员变量和局部变量

成员变量

定义在类中的变量,称为成员变量,有默认值

数据类型

默认值

整型

0

浮点型

0.0

布尔型

false

引用类型(类、数组、接口)

null

class Person(){String name;//成员变量,String是类类型,属于引用类型,默认为nullint age;//整型,默认0void fun(){System.out.println((name));//这里能通过编译,可以使用name,输出nullSystem.out.println(list[0]);//这里能通过编译,由于list为null,会报空指针异常}
}

局部变量

定义在方法中的变量,称为局部变量,没有默认值,赋值后才能使用

class Test{public static void main(String[] args){int num;//定义在方法中的变量称为局部变量,赋值后才能使用System.out.println(num);//无法通过编译}
}

成员变量和局部变量相关面试题

简述成员变量和局部变量的区别以及生命周期

成员变量是定义在类中的变量,有默认值,不赋值也能使用

局部变量是定义在方法中的变量,没有默认值,需要赋值后才能使用

成员变量的生命周期:类创建对象,成员变量就会初始化,类的对象被回收,成员变量就会销毁

局部变量的生命周期:方法调用,对局部变量赋值,局部变量初始化,方法调用结束,局部变量失效

构造方法

概念

构造方法也称为构造函数、构造器、constructor

它是一个特殊的方法。

没有返回值部分,方法名和类名一致,在创建对象时通过new调用,给类的成员变量赋值。

class Person{//成员变量String name;int age;//这就是一个无参数的构造方法,用于new Person()Person(){}//这就是一个带参数的构造方法,用于new Person("admin",20)Person(String name,int age){this.name=name;//将参数的值赋值给成员变量this.age=age;}
}

特点

  1. 创建对象时必须通过new配合构造方法

  1. 创建对象时必须通过new配合构造方法

  1. 构造方法可以存在多个,但是参数不能相同。这些构造方法之间的关系称为方法重载

  1. 每个类默认有一个隐藏的无参数的构造方法,方法体中隐含了一句super()。用于创建无参数的对象

5.如果自己写了带参数的构造方法,默认无参数的构造方法就会失效。如果想要同时拥有带参数和不带参数的构造方法,就需要再次显式的写出来

6.带参数的构造方法常用于初始化成员变量(给类中的变量赋值)

7.构造方法可以限制创建对象时携带的参数

8.构造方法无法通过"."操作符访问,只能通过new关键字创建对象时调用

IDEA中自动生成构造方法

在类空白处右键generate或快捷键alt+insert

在弹出的窗口中,选择Constructor

选择生成的构造方法的参数,全选ctrl+a

面对对象语言的三大特性--封装

封装

使用private关键字对成员变量进行修饰,再提供一组get和set的方法,用于对该属性读取和赋值

可以防止除自身类之外的地方对private修饰的属性进行访问

这样就能保护关键属性或给属性赋一个合理的值

步骤

1.创建类,编写成员变量,对成员变量使用private修饰

class Person{private String name;private int age;
}

2.给所有成员变量添加set方法,用于赋值

void setName(String name){this.name=name;
}
void setAge(int age){this.age=age;
}

3.给所有成员变量添加get方法,用于读取

String getName(){return name;
}
int getAge(){return age;
}

创建该类对象后,无法直接通过.访问属性,只能通过get/set读取和赋值

public static void main(String[] args){Person p = new Person();//p.name;//无法通过.访问被private修饰的属性p.setName("王海");String name = p.getName();
}

IDEA中自动生成getter/setter方法

在类中空白处右键generate或快捷键alt + insert,在弹出的窗口中选择getter and setter

在弹出的窗口中,选择要生成get和set方法的成员变量

IDEA中自动使用变量接收对象

在对象后.var或快捷键ctrl+alt+v

public static void main(String[] args) {//创建对象自动使用变量保存 ctrl + alt + v 或 对象.varEmployee employee = new Employee();
}

Windows中的快捷键

windows + D 进入桌面

windows + E 进入文件资源管理器

Typora中的快捷键

1-6级标题 CTRL + 1~6

加粗 选中文字 CTRL + B

倾斜 选中文字 CTRL + I

倾斜 选中文字 CTRL + U

列表 - 空格 缩进 tab

表格 CTRL + T

整段代码 ```语言

嵌入代码 代码

IDEA中常用快捷键

复制粘贴 CTRL + D

自动接收对象 CTRL + ALT + V

自动生成构造方法等 ALT + Insert

自动调整格式 CTRL + ALT + L

删除整行 CTRL + X

CTRL + Y 可以设置为删除整行或配合撤销(CTRL + Z)恢复

IDEA中常用设置

字体

开启忽略大小写匹配

面向对象综合练习--简易xxx管理

图书类Book

package test4;
/*
图书类
书名
作者
类型
出版社
价格定义私有属性
自动生成全参构造方法,无参构造方法getter/setter、toString()*/
public class Book {private int id;//封装属性private String name;private String author;private String type;private String publisher;private double price;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;}Book(){}@Overridepublic String toString() {return "Book{" +"id=" + id +", name='" + name + '\'' +", author='" + author + '\'' +", type='" + type + '\'' +", publisher='" + publisher + '\'' +", price=" + price +'}';}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;}
}

管理员类Manager

package test4;import java.util.Arrays;/*
图书管理员
属性保存图书的容器方法增加图书删除图书修改图书查看图书*/
public class Manager {//保存图书的容器,该睡醒只能当前类使用,使用private修饰,不提供get/setprivate Book[] booklist=new Book[20];//添加void addBook(Book book){for (int i=0;i<booklist.length;i++){if (booklist[i]==null){booklist[i]=book;//停止循环 防止装满break;}}}//查看所有图书及图书的详细信息void showall(){for (int i=0;i<booklist.length;i++){if (booklist[i]!=null){System.out.println(booklist[i]);}}}//通过图书编号id删除void delete(int id){for (int i=0;i<booklist.length;i++){Book book=booklist[i];if (book!=null && book.getId()==id){book = null;break;}}}//通过id到对应的图书对象Book getBookById(int id){//遍历当前所有的图书对象for (int i=0;i<booklist.length;i++){Book book=booklist[i];//如果遍历未发现满足条件,返回nullif (book!=null && book.getId()==id){//返回对应的图书return book;}}//如果遍历未发现满足条件,返回nullreturn null;}//查看所有图书void showallbookname(){for (int i=0;i<booklist.length;i++){if (booklist[i]!=null) {
//                System.out.println(booklist[i].getName());System.out.println();}}}//修改图书信息,比如价格void update(int id,double newPrice){//根据id获取需要修改的图书//调用当前类中定义的根据id查询Book对象的方法Book book=getBookById(id);if (book!=null){book.setPrice(newPrice);}else {System.out.println("该图书不存在");}}public static void main(String[] args) {Manager manager = new Manager();//通过全参的方法创建对象Book book=new Book(10010,"天龙八部","金庸","小说","xxxx",66);manager.addBook(book);//通过无参构造方法创建对象Book book1=new Book();//通过set方法赋值book1.setId(10011);book1.setName("老人与海");book1.setAuthor("海明威");book1.setType("小说");book1.setPublisher("天津人民出版社");book1.setPrice(10);manager.addBook(book1);manager.showall();}
}

程序入口类Main

package test4;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.退出");int input=sc.nextInt();switch (input){case 1:Random rd=new Random();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("请输入图书价格:");int price=sc.nextInt();//创建一个图书对象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("请输入要修改的价格:");int updatePrice=sc.nextInt();double newPrice=sc.nextDouble();manager.update(updateId,updatePrice);System.out.println("修改成功!");break;case 3:System.out.println("请输入需要删除图书的编号:");manager.delete(sc.nextInt());break;case 4:manager.showallbookname();break;case 5:manager.showall();break;case 6:System.exit(0);break;}}}
}

面向对象三大特性--继承

概念

类B使用extends(延伸)关键字"继承"类A。

语法:class 类B extends 类A{}

类B称为类A的子类,衍生类,subClass

类A称为类B的父类,超类、supClass

继承后,子类就能访问父类中的非私有(没有使用private修饰)成员变量和成员方法。

class A{
private String secret="父类中的私有属性";
String name="父类";
void info(){
System.out.println("父类中的非私有方法");
}
}
class B extends A{
void fun(){
System.out.println(secret);//无法访问父类中的私有成员变量
System.out.println(name);//可以访问非私有成员变量
info();//可以直接调用父类中的非私有方法
}
}
  • 将多个类中的公共代码提取出来保存到一个公共类中,这些类使用extends"继承"这一个公共类,从而减少这些类中的冗余代码。

  • 如猫类、狗类都有类型、昵称等属性,也有吃、睡等方法,那就可以定义一个动物类,将这些公共的属性和方法定义在动物类这个父类中,再让猫类和狗类这些子类继承动物类。这样就能直接通过子类访问父类中的内容。

特点

  1. 如果多个类之中有相同的代码,可以将这些代码提取出来到一个公共的类中,这个类就是父类。再让那些类去extends继承这个父类,那些类就是子类。子类就无需再写重复代码

  1. 子类中或子类对象可以直接访问父类中非私有(不用private修饰)属性和方法

  1. 创建子类对象时,会先执行父类中相应的构造方法

  1. 子类继承父类后,通常会对对父类中的方法进行拓展或覆盖,这称为方法重写。重写后,子类再调

用该方法时,执行的是重写后的内容

  1. Java中是单继承。一个子类只能extends一个父类,一个父类可以有很多子类

  1. Java中可以多重继承,类A可以继承类B,类B继承类C,这是类A既是类B的子类,也是类C的子

类,类A可以访问类B和类C中的非私有成员

  1. 任何类都是Object类的子类

方法重写和方法重载

方法重写override

当子类继承父类后,可以对父类中的方法进行扩展或覆盖。这个过程称为方法重写。

方法重写要求

方法名、返回值、参数列表必须和父类一致

访问权限不能比父类更严格(访问修饰符的范围要么一致要么更大)

不能抛出比父类更大的异常

IDEA中如果要重写方法,使用CTRL + O在弹出的窗口中选择要重写的方法

方法重载overload

在一个类中,如果多个方法的方法名相同,参数列表不同时,这些方法称为重载的方法。

同名不同参。

重载用于,在一个类中,某个方法在不同的条件下,执行不同的内容。

方法重载要求

方法名相同

参数必须不同(数量、类型)

与返回值无关

重载和重写相关面试题

说出重载与重写的异同

相同点:方法名不变

不同点:

重载在一个类中,重写在继承关系中子类重写父类

重载参数必须不同,重写参数必须相同

重载返回值无要求,重写返回值必须相同

构造方法能重载吗?能重写吗?

构造方法可以重载。构造方法不能重写。

构造方法在执行时,一定会创建对象吗?

不一定。创建子类时会自动执行父类构造方法,但不会创建父类对象。

以下代码执行会输出什么结果

class Father(){Father(){fun();}void fun(){System.out.println("父类中的普通方法");}
}class Son extends Father{Son(){fun();}void fun(){System.out.println("子类中的普通方法");}
}class Test{public static void main(String[] args){//1.创建父类对象,调用父类中无参构造方法//2.无参构造方法中调用fun(),调用父类中的方法,输出“父类中的普通方法”new Father();//父类中的普通方法//1.创建子类对象,先调用父类中无参构造方法//2.无参构造方法中调用fun(),由于fun()子类对其进行了重写,调用的是重写后的方法,输出"子类中的普通方法"//3.执行子类中无参构造方法,调用重写后的fun(),输出“子类中的普通方法”new Son();//"子类中的普通方法"打印两次}
}
//最终输出
//父类中的普通方法
//子类中的普通方法
//子类中的普通方法

this和super关键字

这两个关键字,都可以当做对象使用,也可当做构造方法使用。

当做对象使用

用法:this.属性或this.方法,super.属性或super.方法

此时的this表示当前类的对象,super表示当前类的父类对象

class Person{private String name;public void setName(String name){//这里的this表示当前类的对象Person对象//相当于Person p = new Person();中的pthis.name=name;}public String getName(){return name;}
}class Man extends Person{void fun(){//这里的super表示当前类的父类对象//Person p = new Person();//super表示上句话中的pSystem.out.println(super.getName());}
}

当做构造方法使用

用法:this([参数])或super([参数])

此时的this([参数])表示当前类的某个构造方法。如this()表示当前类的无参构造方法。

super([参数])表示当前类的父类的某个方法。如super()表示当前类的父类的无参构造方法。

如果当做构造方法使用时,只能写在另一个构造方法的第一行。

class Person{String name;int age;Person(){}Person(String name,int age){this.name=name;this.age=age;}
}class Woman extends Person{Woman(){super("admin",20);}
}class Main{public static void main(String[] args){//调用Woman中的无参构造方法//super("admin",20),执行父类中的 Person(String name,int age)new Woman();}
}

注意

如果父类中有无参数的构造方法,在子类的构造方法中,可以不写super(),默认自动调用。

如果父类中有带参数的构造方法,没有无参数的构造方法,在子类的构造方法中,必须要有super([参

数])

  • 父类和子类中都没有构造方法(只有默认的无参构造方法)

class Father{//默认会有/*public Father(){}*/
}class Son extends Father{//默认会有/*public Son(){super();}*/
}
  • 父类中没有无参构造方法,子类中就必须调用父类中对应的构造方法

class Father{String name;//由于该构造方法的出现,默认无参数的构造方法就会失效Father(String name){this.name=name;}
}//这时子类继承会报错
class Son extends Father{//因为每个类中都有这段代码/*Son(){//但当前继承的父类中没有无参构造方法super();}*/
}//解决方式1.给父类中添加无参构造方法
class Father{String name;Father(String name){this.name=name;}Father(){}
}//解决方式2.子类中添加同样的构造方法,目的是为了调用父类中的对应构造方法
class Son extends Father{Son(String name){super(name);}
}

作业:模拟组装手机

摄像头类

package test5;
/*
camera:摄像头
像素:pixel*/
public class Camera extends Hardware{private String pixel;public Camera(String name, String pixel) {super(name);this.pixel = pixel;}
}

处理器类

package test5;
/*
processor:处理器
频率
品牌
型号*/public class Processor extends Hardware{private String frequency;private String type;public Processor(String name, String frequency, String type) {super(name);this.frequency = frequency;this.type = type;}
}

屏幕类

package test5;
/*
screen:屏幕
品牌
分辨率,size
材质,material*/
public class Screen extends Hardware{private String size;private String material;public Screen(String name, String size, String material) {super(name);this.size = size;this.material = material;}}

硬件类

package test5;
/*
公共属性
品牌*/
public class Hardware {private String name;public Hardware(String name) {this.name = name;}@Overridepublic String toString() {return "Hardware{" +"name='" + name + '\'' +'}';}public String getName() {return name;}public void setName(String name) {this.name = name;}
}

程序入口Main方法

package test5;import java.util.Random;
import java.util.Scanner;public class Main {public static void main(String[] args) {Processor processor1 = new Processor("因特尔/Inter","3.60Ghz","奔腾");Processor processor2 = new Processor("酷睿/kr","5Ghz","Inter 酷睿 i5");Processor processor3 = new Processor("AMD","5.9G","Ryzen 5");Screen screen1 = new Screen("ips屏幕-1080p","1920*1080","液晶面板");Screen screen2 = new Screen("led屏幕-p10","80*60","led晶片,反光杯,金属阳极,金属阴极");Camera camera1 = new Camera("小米","1.8亿像素");Camera camera2 = new Camera("华为","5000万像素");Camera camera3 = new Camera("海康威视","400万像素");Processor[] processors=new Processor[3];processors[0]=processor1;processors[1]=processor2;processors[2]=processor3;Screen[] screens = new Screen[2];screens[0] = screen1;screens[1] = screen2;Camera[] cameras=new Camera[3];cameras[0] = camera1;cameras[1] = camera2;cameras[2] = camera3;Random rd=new Random();for (int i=0;i<5;i++){int index1= rd.nextInt(3);int index2= rd.nextInt(2);int index3= rd.nextInt(3);System.out.println("Processor:"+processors[index1]);System.out.println("Screen:"+screens[index2]);System.out.println("Camera:"+cameras[index3]);System.out.println("----------------------");}}
}

包package

通过包可以将.java源文件进行结构化管理,相当于windows中的文件夹。

不同的包中,可以保存相同的.java源文件。

某个类在某个包中时,会在该类的代码最上加入 package 包名 ;

包的命名

包名通常使用公司域名的倒序形式。

如baidu.com是百度的域名,有一个test的项目,包名写为com.baidu.test

包名中的".",相当于进入文件夹

如com.baidu.test,会创建3个文件夹:com下有baidu,baidu下有test。

导入包

如a包中的类要使用b包中的类时,需要在a包中的类中,导入b包或b包中的某个类。

如在使用Scanner时,就需要导入Scanner所在的java.util包。 import java.util.Scanner;

在IDEA中,如果是通过自动补全的形式写的代码,会自动导入该类,

或设置自动导包删包。

如果需要手动导入包,在报错的位置上按下快捷键alt+回车,

如果多个类,类名相同但在不同的包中,使用该类时选择合适的包。

访问修饰符

访问修饰符可以限制某个类、属性或方法的访问权限

用法:

修饰类:访问修饰符 class 类名{}

修饰属性:访问修饰符 数据类型 变量名;

修饰方法:访问修饰符 返回值类型 方法名(){}

访问修饰符

含义

可以修饰

public

公共的

类、方法、属性

protected

受保护的

方法、属性

不写

默认的

类、方法、属性

private

私有的

方法、属性

访问权限表

同一个类中

同一个包中的不同类

不同包中的子类

不同包中的非子类

public

protected

×

不写

×

×

private

×

×

×

访问权限从大到小

public >>> protected >>> 默认的 >>> private

final关键字

修饰属性

当final修饰属性时,该属性的值不可更改,这个属性称为常量。

常量在程序运行过程中,保存的值不能编号,所以定义常量时需要初始化。

常量名所有字母大写,多个单词之间用_隔开。

final 数据类型 常量名;
final int NUM = 123;
final double PI = 3.14;

修饰方法

当final修饰方法时,该方法不能被重写。

在方法的返回值前加上final。

public class Father{public final void fun(){}
}public class Son extends Father{//会报错,无法对final方法进行重写@Overridepublic void fun(){}
}

修饰类

当final修饰类时,该类不能被继承。

定义类,在class前加final

public final class Father{public final void fun(){}
}//会报错,提示该类无法继承Father
public class Son extends Father{}

创建对象时的内存变化

Object类

是java中所有类的父类。每个类都是这个类的子类,但没有使用extends体现出来

该类中定义了很多方法,通常需要进行重写。

对象造型/对象转型/cast

类似于原始类型中的数据类型转换。对象A转换为对象B的过程,称为对象转型。

在非继承关系的两个对象中,无法转型。

向下转型

父类对象转换为子类对象的过程,称为向下转型。强制转换

//一个父类对象
Object obj = new Object();
//默认无法直接将obj使用Person对象接收
//"强制转换"
Person p = (Person) obj;

向上转型

子类对象转换为父类对象的过程,称为向上转型。自动转换

//一个子类对象
Person p = new Person();
//默认子类对象可以用父类变量接收 多态
Object obj = p;

重写equals方法

如果两个对象的属性全部相同,在日常的业务逻辑中,可以视为这两个对象是同一个对象。

但是默认使用new创建的对象,就算属性一致,也是不同的内存地址,

如果用==比较,比较的是对象的内存地址,地址不同,返回false。

所以对象比较相同不能使用==

这时就需要自定义一套比较的方

这时就需要自定义一套比较的方法,Object中有一个equals方法,用于比较两个对象是否相同,

但是Object中的equals方法用==比较,所以对该方法进行重写。

如两个Student的id、name、sex都一致,返回true.

@Override
public boolean equals(Object obj) {//将Object对象转换为当前类Student对象if (this == obj) {return true;
}
//判断参数是否为Student类型
//对象 instanceof 类 检测对象是否属于指定类型if (obj instanceof Student) {//使用"强制转换"将父类对象转换为子类对象,称为向下转型Student student = (Student) obj;if (this.id == student.id &&this.name.equals(student.name) &&this.sex.equals(student.sex)) {return true;}}return false;
}

在IDEA中自动生成equals方法

在类中右键generate或快捷键alt + insert,选择equals and hashcode,选择属性。

如两个对象的id相同就视为同一个对象,可以只选择id属性;

如两个对象的所有属性相同才视为同一个对象,选择全部属性。

同时生成的hashcode()可以删除

面向对象三大特性--多态

子类的对象保存在父类的变量中。

父类 变量 = new 子类();

public class Father{}public class Son extends Father{}public class Test{public static void main(String[] args){//多态:子类的对象保存在父类的变量中Father f = new Son();}
}

多态的应用

当某个方法的参数为父类变量时,可以传递一个子类对象。

这样就能在传递不同的子类对象时,表现出不同的形态。

如 要定义动物发出叫声的方法,参数是猫,输出猫对象的叫的方法"喵喵",参数是狗,输出狗对象的叫

的方法"汪汪"。

不用多态,需要写很多重载的方法,参数为猫或狗或其他类型。

使用多态,只需一个方法,参数为动物类,在动物类中定义叫的方法,让子类猫类狗类对其进行重写。

这时调用动物的叫的方法,实际会根据动物子类对象,调用具体子类重写后的方法。

多态的前提

在继承关系中

父类的变量保存子类的对象(向上转型)

作业模拟游戏厅

玩家类

package com.hqyj.homework;import java.util.Objects;/** 玩家类* 属性*   用户名*   密码*   余额* */
public class Player {private String name;private String password;private double balance;/** 如果用户名和密码相同,equals比较结果为true* */@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Player player = (Player) o;return Objects.equals(name, player.name) && Objects.equals(password, player.password);}@Overridepublic String toString() {return "Player{" +"name='" + name + '\'' +", password='" + password + '\'' +", balance=" + balance +'}';}/** 只包含用户名和密码的构造方法,用于登录* */public Player(String name, String password) {this.name = name;this.password = password;}/** 全参构造,用于给所有参数赋值* */public Player(String name, String password, double balance) {this.name = name;this.password = password;this.balance = balance;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public double getBalance() {return balance;}public void setBalance(double balance) {this.balance = balance;}
}

游戏类

package com.hqyj.homework;/** 游戏类* 属性** 方法*   开始游戏** */
public abstract class Game {/**  游戏父类,定义玩游戏的方法,参数为玩家对象* 如果一个方法没有方法体,可以将其定义为抽象方法,在返回值前使用abstract修饰* 如果一个类中有抽象方法,这个类必须是抽象类,类名前使用abstract修饰* */public abstract void start(Player player);
}

游戏子类

package com.hqyj.homework;import java.util.Random;
import java.util.Scanner;/** 游戏子类:石头剪刀布* */
public class GameDemo extends Game {@Overridepublic void start(Player player) {//生成1-3的随机数代表电脑出拳石头、剪刀、布int com = new Random().nextInt(3) + 1;System.out.println("请出拳:1.石头\t2.剪刀\t3.布");Scanner sc = new Scanner(System.in);int input = sc.nextInt();if (input < 1 || input > 3) {System.out.println("请输入正确的数字");return;}//扣钱player.setBalance(player.getBalance()-2);//判断电脑出拳switch (com) {case 1://判断玩家出拳if (input == 1) {System.out.println("你出的是石头,电脑出的是石头,平局!");} else if (input == 2) {System.out.println("你出的是剪刀,电脑出的是石头,你输了!");} else {System.out.println("你出的是布,电脑出的是石头,你赢了!");player.setBalance(player.getBalance()+4);}break;case 2:if (input == 1) {System.out.println("你出的是石头,电脑出的是剪刀,你赢了!");player.setBalance(player.getBalance()+4);} else if (input == 2) {System.out.println("你出的是剪刀,电脑出的是剪刀,平局!");} else {System.out.println("你出的是布,电脑出的是剪刀,你输了!");}break;case 3:if (input == 1) {System.out.println("你出的是石头,电脑出的是布,你输了!");} else if (input == 2) {System.out.println("你出的是剪刀,电脑出的是布,你赢了!");player.setBalance(player.getBalance()+4);} else {System.out.println("你出的是布,电脑出的是布,平局!");}break;}}
}

游戏子类

package com.hqyj.homework;import java.util.Random;
import java.util.Scanner;public class GuessNum extends Game {/** 重写玩游戏的方法,实际是该类表示的游戏子类的具体玩法* */@Overridepublic void start(Player player) {//随机1-100猜数int ans = new Random().nextInt(100) + 1;Scanner sc = new Scanner(System.in);while (true) {//判断余额if (player.getBalance() <= 0) {System.out.println("余额不足,请充值");break;}//扣钱double newBalance = player.getBalance() - 2;player.setBalance(newBalance);//开始游戏System.out.println("请猜数");int input = sc.nextInt();if (input > ans) {System.out.println("猜大了!");} else if (input < ans) {System.out.println("猜小了!");} else {System.out.println("猜对了!");//加钱player.setBalance(player.getBalance() + 10);break;}}}
}

游戏厅类

package com.hqyj.homework;import java.util.Scanner;/** 游戏厅类* 属性*   玩家集合** 方法*   注册*   登录*   玩游戏*   充值* */
public class GameHouse {//玩家对象数组private Player[] playerList = new Player[10];/** 注册* */public boolean register(Player player) {//遍历当前玩家集合for (Player p : playerList) {//如果注册的玩家名称已存在,无法注册if (p != null && p.getName().equals(player.getName())) {System.out.println("该用户已存在");return false;}}//添加参数到数组中for (int i = 0; i < playerList.length; i++) {if (playerList[i] == null) {playerList[i] = player;System.out.println("注册成功");return true;}}System.out.println("人数已达上限");return false;}/** 登录* 参数为只有账号密码的玩家对象* 返回值为null或有账号密码和余额的玩家对象* */public Player login(Player player) {for (Player p : playerList) {if (p != null && p.equals(player)) {//返回已存在的玩家对象return p;}}return null;}/** 充值* */public void charge(Player player){System.out.println("请输入充值金额");Scanner sc = new Scanner(System.in);int money = sc.nextInt();if(money>0){player.setBalance(player.getBalance()+money);}else{System.out.println("不能是负数");}}/** 玩家玩游戏* */public void playGame(Game game,Player player){game.start(player);}
}

程序入口Main方法

package com.hqyj.homework;import java.util.Scanner;public class Main {public static void main(String[] args) {Main main = new Main();main.menu();}Scanner sc = new Scanner(System.in);GameHouse gh = new GameHouse();/** 系统菜单* */public void menu() {System.out.println("1.登录\t2.注册\t3.退出");switch (sc.nextInt()) {case 1:System.out.println("请输入用户名");String loginName = sc.next();System.out.println("请输入密码");String loginPwd = sc.next();//登录对象Player player = new Player(loginName, loginPwd);//登录后的对象Player login = gh.login(player);if (login == null) {System.out.println("用户名或密码错误");} else {//进入玩家菜单playerMenu(login);}break;case 2:System.out.println("请输入用户名");String regName = sc.next();System.out.println("请输入密码");String regPwd = sc.next();//注册对象Player regPlayer = new Player(regName, regPwd);//调用注册gh.register(regPlayer);//注册成功,跳转到本方法break;case 3:System.exit(0);break;}menu();//递归调用}/** 玩家菜单* */public void playerMenu(Player player) {System.out.println("1.查看个人信息\t2.充值\t3.玩游戏\t4.返回主界面");switch (sc.nextInt()) {case 1:System.out.println(player);break;case 2:gh.charge(player);break;case 3://进入游戏菜单gameMenu(player);break;case 4://调用主菜单menu();break;}playerMenu(player);}/** 游戏界面* */public void gameMenu(Player player){System.out.println("1.猜数游戏\t2.猜拳游戏\t3.返回玩家界面");switch (sc.nextInt()) {case 1:GuessNum guessNum = new GuessNum();gh.playGame(guessNum,player);break;case 2:gh.playGame(new GameDemo(),player);break;case 3://进入玩家菜单playerMenu(player);break;}gameMenu(player);}
}

abstract抽象的

修饰方法

使用:访问修饰符 abstract 返回值类型 方法名(参数列表);

如果一个方法的方法体无法描述,是由其子类进行重写后使用,可以将这个方法定义为抽象方法。

该方法就可以去掉方法体部分,该方法的所在类,也必须是一个抽象类,使用abstract修饰。

修饰类

使用:访问修饰符 abstract class 类名{}

如果一个类中有抽象方法,这个类必须也是一个抽象类。

//当一个类中有抽象方法时,这个类也必须是抽象类
public abstract class Fruit{//当一个方法没有方法体时,这个方法定义为抽象方法public abstract void eatIt();
}

abstract关键字特点

修饰类:被修饰的类称为抽象类

抽象类不能被实例化(不能创建对象);

抽象类中有构造方法,在创建其子类对象时自动调用。

抽象类中可以有普通方法,通过其子类对象主动调用。

抽象类中定义的所有抽象方法,子类要么全部进行重写,要么也定义为抽象类

修饰方法:被修饰的方法称为抽象方法

抽象方法没有方法体

抽象方法只能出现在抽象类中

abstract不能修饰构造方法和静态方法

抽象相关面试题

抽象类的特点?

  • 抽象类是使用abstract修饰的类,除了不能创建对象、能定义抽象方法外,与普通类一样。抽象方法的特点?

  • 抽象方法是使用abstract修饰的方法,没有方法体。非抽象子类必须要对父类中的抽象方法进行重写。

抽象类中有构造方法吗?

  • 有构造方法,但不是通过new该类对象时调用,而是在new其子类对象时自动调用。

执行某个类的构造方法时,一定会创建这个类的对象吗?

  • 不一定

  • 如果是普通类,在执行构造方法时,一定会创建对象

  • 如果是抽象类,在执行构造方法时,不会创建自身对象,只会创建其子类对象

接口interface

在Java中,数据类型分为基本类型和引用类型。

引用类型包含:数组、类和接口。

所以接口是一种数据类型,类似于类,在定义接口的时候,使用interface替换class。

由于Java是单继承,如果类A既要继承类B中的内容,也要继承类C中的内容时,

如果用"extends class名",只能选择一个类继承,

但使用implements interface名1,interface名2...就能同时"继承"多个"父类".这里的"父类"就是接口。

通常用extends表示类A继承类B,用implements表示类A实现接口A,接口B...

一个类可以同时implements实现("继承")多个接口。

extends和implements

类A extends 类B

类A当做类B的子类,称为继承

类A implements 接口A,接口B...

类A当做类B的实现类,称为实现

接口A extends 接口B

接口A继承接口B

类A extends 类B implements 接口A,接口B...

类A是类B的子类,同时也是接口A,接口B的实现类

什么时候使用接口

如果想要让某个类作为多个"类"的子类时,将这些"父类"定义为接口

如果某个类中的所有方法都是抽象方法时,将这个抽象类改为接口

定义接口

public interface 接口名{//接口中只能定义公开的静态常量并且要赋值//接口中的方法一般都是公开的抽象方法 public abstract ,如果要定义,默认就有这两个关键字//public abstract void fun();void fun();//这句话相当于上一句,默认接口中的抽象方法使用public abstract修饰//jdk1.8后,可以在接口中定义"默认"方法,使用default修饰的方法default void test(){}//jdk1.8后,可以在接口中定义静态方法,使用static修饰的方法staic void test2(){}
}

接口案例

USB接口

package com.hqyj.test3;/*
* 定义USB接口
* 只需定义有哪些功能,无需实现。子类实现功能
*
* 方法
* 连接
* 退出
* */
public interface USB {//接口中定义的方法都是抽象方法,默认使用public abstract修饰,可以不写//public abstract void fun();void start();void stop();//接口中可以定义被default修饰的默认方法default void fun1(){System.out.println("接口中定义的默认方法");}//接口中可以定义被static修饰的静态方法static void fun2(){System.out.println("接口中定义的静态方法");}//接口中定义的属性是被public final static修饰,称为公共的静态常量,必须要有初始值public final static int num=5;}

USB接口的实现类--鼠标类和键盘类

package com.hqyj.test3;
import java.io.Serializable;
/*
* 定义USB接口的实现类:鼠标类
* 接口的实现类只需实现接口中的抽象方法
* */
public class Mouse implements USB {@Overridepublic void start() {System.out.println("鼠标接入");}/** 抽象方法一定要重写* */@Overridepublic void stop() {System.out.println("鼠标退出");//子实现类中直接访问父接口中的默认方法,选择性重写//fun1();//通过接口名直接访问接口中的静态方法,静态方法无法重写//USB.fun2();}
}package com.hqyj.test3;
public class Keyboard implements USB {private String name;public Keyboard(String name) {this.name = name;
}@Overridepublic void start() {System.out.println(name + "键盘接入");}@Overridepublic void stop() {System.out.println(name + "键盘退出");}
}

使用接口的类--电脑类

package com.hqyj.test3;/*
* 电脑类
* 方法
* 开机
* 启动USB设备
* 关机
* 停止USB设备
* */
public class Computer {/** 开机* */public void powerOn(USB usb1, USB usb2) {System.out.println("电脑开机。。。");if (usb1 != null) {usb1.start();} else {System.out.println("当前USB1插槽没有设备");}if (usb2 != null) {usb2.start();} else {System.out.println("当前USB2插槽没有设备");}}public void powerOff(USB... usbs) {System.out.println("电脑关机。。。");//遍历可变参数for (USB usb : usbs) {usb.stop();}}
}

Main

package com.hqyj.test3;/*
* 模拟电脑使用USB设备
* 主机都有"USB接口",定义主机类,定义一些方法,参数为"USB设备"
* 所有“USB设置”都有连接和退出功能
*
*
* */
public class Main {public static void main(String[] args) {Computer computer = new Computer();//接口对象无法实例化(无法创建对象)//USB usb = new USB();//创建接口的实现类对象,可以用自身接收,也可以用父接口变量接收Mouse mouse = new Mouse();USB keyboard = new Keyboard("罗技");computer.powerOn(mouse, keyboard);//可变参数的方法传递参数时,可以是任意数量个参数,但这些参数类型必须统一computer.powerOff(mouse,keyboard);}
}

抽象类和接口的异同

抽象类是一个类,用abstract class定义

  • 有构造方法,不能创建对象,在创建子类对象时自动调用父抽象类中的构造方法

  • 抽象类中可以有非抽象方法

  • 抽象类被子类继承时,用extends关键字。子类需要重写父抽象类中的所有抽象方法

  • 子类只能继承一个抽象类

  • 抽象类中可以定义成员变量

接口不是一个类,用interface定义

  • 没有构造方法,不能创建对象

  • 接口中定义抽象方法时,无需加public abstract修饰符

  • 接口中可以存在被default或static修饰的方法

  • 接口被子类实现时,用implements关键字。子类需要重写父接口中的所有抽象方法

  • 子类可以实现多个接口,用逗号隔开

  • 接口中定义的属性都是公共的静态常量,被public static final修饰,必须要有初始值

相同点

  • 接口和抽象类都无法创建对象

  • 接口的实现类和抽象类的子类,都需要重写抽象方法

接口是一个完全抽象类。JDK1.8之后可以在接口中定义有方法体(被default或static修饰)的方法。

static静态的

每次new创建一个对象,都会在堆空间中开辟一块区域,这个过程是需要花费时间和空间的。

在栈空间中,只会定义变量,保存堆空间中某块区域的地址。通过变量访问堆空间中对应地址的数据。

如果多个对象都有相同的属性或方法时,可以将这些公共的属性和方法使用static修饰,

让其成为静态数据,在类加载的时候就保存在静态区中

在不使用静态成员时

如上图的"重庆大学"这个字符串,每个对象都会使用,就可以将其使用static关键字,定义为静态属性。

静态属性或静态方法,在类加载时就会保存到内存中,无论是否创建对象都能访问,通过类名直接访

问。

使用静态成员时

概念

static是一个修饰符,可以修饰属性、方法、代码块。

被static修饰的内容,称为静态成员。静态成员在类加载时就保存到内中。

访问静态成员时,可以不用创建对象,直接通过类名访问。

如Math中的所有属性和方法,都是静态的,都通过Math直接访问。

定义和访问

public class DBUtil{//静态属性,通常配合public final定义为公共的静态常量public static final int NUM=5;//静态方法public static Connection getConn(){//连接数据库操作return conn;}//静态代码块static{//代码;}
}public class Test{public static void main(String[] args){//静态属性和方法直接通过类名访问System.out.println(DBUtil.NUM);//调用静态方法或创建对象时,自动执行一次静态代码块DBUtil.getConn();//也可以通过对象访问静态成员,但通常通过类名访问new DBUtil().getConn();}
}

什么时候使用static

如果某个属性或方法被高度重用时,可以将其定义为static静态的。

这样这些属性和方法在类加载时就会加载到内存中,从而直接通过类名即可访问。

static特点

  • 静态方法中只能使用静态成员,不能使用非静态成员

public class Student{static String STR="静态成员变量";int num=123;public static void fun(){System.out.println(STR);//可以访问System.out.println(num);//不能访问}
}
  • 非静态方法中,可以访问非静态或静态成员

public class Student{static String STR="静态成员变量";int num=123;public void fun(){System.out.println(STR);//可以访问System.out.println(num);//可以访问}
}
  • 静态方法中不能使用this或super关键字

成员变量、局部变量、静态常量

成员变量:定义在类中的变量

成员变量随着对象的创建而存在,随着对象的回收而销毁。

作用范围在类内部,成员变量有初始值。

局部变量:定义在方法中的变量

局部变量随着方法的调用而存在,随着方法执行结束而销毁。

作用范围在方法内容,局部变量没有初始值,必须赋值后才能使用。

静态常量:被final、static修饰的成员变量

静态常量随着类加载而存在,随着类的销毁而销毁(通常程序运行结束).

作用范围在程序运行周期中,静态量有初始值,静态常量必须赋值。

public class ZOO {//静态常量public static final String ZOO_NAME = "重庆动物园";//成员变量private String address;public ZOO(String address) {this.address = address;}//静态方法public static void welcome() {//只能使用静态常量System.out.println("欢迎光临" + ZOO_NAME);}//成员方法public void sayHello(Animal animal) {//局部变量String str = "你好";System.out.println(ZOO_NAME + "中的" + animal.getType() + "打招呼说" +
str);System.out.println("地址:"+address);}
}public class Animal {private String type;public Animal(String type){this.type=type;}public String getType() {return type;}public void setType(String type) {this.type = type;}
}public class Main {public static void main(String[] args) {ZOO.welcome();Animal bear = new Animal("棕熊");new ZOO("杨家坪").sayHello(bear);}
}

作业模拟游戏人物PK

游戏角色类

package homework;import java.util.Objects;/*
* 游戏角色类
* */
public class Hero {private String name;private String weapon;private String skill;private int hp=1000;@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Hero hero = (Hero) o;return Objects.equals(name, hero.name) && Objects.equals(weapon, hero.weapon) && Objects.equals(skill, hero.skill);}@Overridepublic String toString() {return "Hero{" +"name='" + name + '\'' +", weapon='" + weapon + '\'' +", skill='" + skill + '\'' +", hp=" + hp +'}';}public Hero(String name, String weapon, String skill) {this.name = name;this.weapon = weapon;this.skill = skill;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getWeapon() {return weapon;}public void setWeapon(String weapon) {this.weapon = weapon;}public String getSkill() {return skill;}public void setSkill(String skill) {this.skill = skill;}public int getHp() {return hp;}public void setHp(int hp) {this.hp = hp;}
}

召唤师类

package homework;import java.util.Random;public class HeroManager {private Hero[] heroes = new Hero[10];/** 添加* 不能添加重复(姓名、武器、技能相同)人物* */public void addHero(Hero hero) {//是否重复for (Hero h : heroes) {if (h != null && h.equals(hero)) {System.out.println(hero.getName() + "已存在");return;}}//添加for (int i = 0; i < heroes.length; i++) {if (heroes[i] == null) {heroes[i] = hero;System.out.println("添加成功");return;}}System.out.println("人数已达上限");}/** 查看所有* */public void showAll() {//定义用于标号的数字int i = 1;for (Hero hero : heroes) {if (hero != null) {//打印时添加标号   toString()方法将对象转换为字符串System.out.println(i++ + ":" + hero);}}}/** 根据编号得到人物对象* */public Hero findById(int id) {//实际1对应下标0return heroes[id - 1];}Random rd = new Random();public void battle(int id1, int id2) throws InterruptedException {Hero h1 = findById(id1);Hero h2 = findById(id2);System.out.println("【" + h1.getName() + "】VS【" + h2.getName() + "】");while (true) {if(h1.getHp()<=0){System.out.println(h1.getName()+"已阵亡");break;}if(h2.getHp()<=0){System.out.println(h2.getName()+"已阵亡");break;}//休眠Thread.sleep(500);//根据数字判断谁发动技能int num = rd.nextInt(9) + 4;int hurt1 = rd.nextInt(51) + 100;int hurt2 = rd.nextInt(51) + 100;//双方if (num == 12) {//技能伤害System.out.println(h1.getName() + "使用" + h1.getWeapon() + "发动" + h1.getSkill() + ",对" + h2.getName() + "造成了" + hurt1 + "伤害");System.out.println(h2.getName() + "使用" + h2.getWeapon() + "发动" + h2.getSkill() + ",对" + h1.getName() + "造成了" + hurt2 + "伤害");h1.setHp(h1.getHp()-hurt2);h2.setHp(h2.getHp()-hurt1);}else if(num%3==0){//其中一方System.out.println(h1.getName() + "使用" + h1.getWeapon() + "发动" + h1.getSkill() + ",对" + h2.getName() + "造成了" + hurt1 + "伤害");h2.setHp(h2.getHp()-hurt1);}else if(num%4==0){//其中一方System.out.println(h2.getName() + "使用" + h2.getWeapon() + "发动" + h2.getSkill() + ",对" + h1.getName() + "造成了" + hurt2 + "伤害");h1.setHp(h1.getHp()-hurt2);}else{System.out.println(h1.getName() + "使用对" + h2.getName() + "进行普通攻击,造成了" + 10 + "伤害");System.out.println(h2.getName() + "使用对" + h1.getName() + "进行普通攻击,造成了" + 10 + "伤害");h1.setHp(h1.getHp()-10);h2.setHp(h2.getHp()-10);}}}
}

Main方法

package homework;import java.util.Scanner;public class Main {public static void main(String[] args) throws InterruptedException {HeroManager hm = new HeroManager();Hero h1 = new Hero("吕布", "方天画戟", "毁天灭地");Hero h2 = new Hero("吕布", "方天画戟", "毁天灭地");Hero h3 = new Hero("貂蝉", "长袖", "跳舞");hm.addHero(h1);hm.addHero(h2);hm.addHero(h3);hm.showAll();Scanner sc = new Scanner(System.in);System.out.println("请输入第一个人物的编号");int id1 = sc.nextInt();System.out.println("请输入第二个人物的编号");int id2 = sc.nextInt();hm.battle(id1, id2);}
}

可变参数

当某个方法的参数是同一种类型且数量未知时,参数列表中可以使用可变参数定义。

修饰符 返回值类型 方法名(数据类型... 形参名){//这时的参数的数量是可变的,[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中的枚举是一个特殊的类,是一些常量的集合。

如星期可以用数字1-7表示,也可以用"周一到周天"表示,

也可以用SUN,MON,TUE,WED,THU,FRI,SAT这些来表示。

这三种都可以称为枚举,对星期这个概念进行枚举。

定义枚举类型

public enum 枚举类型名{常量1,常量2...常量N
}

使用枚举类型

枚举类型名.常量名;
package test1;
/*
* 定义枚举类型
* 使用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("单词有误");}}
}

内部类

内部类,是指定义在类中的类。

内部类通常使用private修饰,定义在类中,用于隐藏类的实现细节,将类进行封装

public class Outer{//内部类通常private私有化,只能当前外部类中才能使用private class Inner{//这就是一个内部类//这里可以定义属性和方法}
}

内部类分为:成员内部类,静态内部类,局部内部类和匿名内部类。

匿名内部类

没有名称的内部类称为匿名内部类。

当某个方法的参数为接口或抽象类对象时,通常会先定义接口的实现类或抽象类的子类,再创建子类对象作为方法的参数。

如果使用匿名内部类,就可以不用创建子类,而是直接通过匿名内部类作为参数使用。

Lambda表达式

JDK8中的核心升级点。

通常用于简化匿名内部类的写法。

要简化的匿名内部类必须是函数式接口(只有一个抽象方法的接口)。

Lambda表达式语法

(参数类型 参数名) -> {代码语句;}

小括号部分表示参数列表

->部分表示要执行什么

{}部分表示执行的内容

使用lambda表达式遍历集合

面向过程和面向对象编程思想

面向过程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();}
}

修饰符

访问修饰符

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{//在调用该类中的方法或创建对象时自动执行一次
}

华清远见重庆中心-面向对象技术总结/个人总结相关推荐

  1. 华清远见重庆中心—面向对象技术总结/个人总结

    编程思想 面向过程编程 Procedure Oriented Programming 简称POP. 是一种基本的编程思想,将一件事情按流程按步骤执行,逻辑清晰. 每一步都是基于上一步的流程去继续实现. ...

  2. 华清远见-重庆中心-前端技术总结/知识点梳理/个人总结/面试题解析

    HTML 1.1什么是HTML 超文本:有视频,音频,图片等,超越文本 超文本标记语言(Hyper Text Markup Language) 标记语言:有一套标签 1.2标签 是由<>包 ...

  3. 华清远见重庆中心-JS技术总结

    js的内容更多更杂,学习更多逻辑上的东西,难度也加大了许多,我将根据老师的笔记以及自己写的代码展开一下内容 数据类型 7 种原始类型 undefined, Boolean,Number, String ...

  4. 华清远见-重庆中心-前端技术阶段

    花了两周多的时间对HTML.CSS.JavaScript和jQuery进行系统性的学习,学习完了后打算花一点时间对之前学习的内容进行复习巩固与总结,划分熟悉程度进行不同程度的梳理,顺便记录. 复习 H ...

  5. 华清远见重庆中心—JavaWeb技术总结/个人总结

    JavaWeb 网站 用户通过浏览器访问某个域名或ip后,浏览到的综合性页面. 实际是发布在服务器上的一个应用程序,通过浏览器访问. 网页 网站中的某张页面 静态页面:所有人看到的内容都一样 动态页面 ...

  6. 华清远见-重庆中心-JavaWeb技术总结

    JavaWeb 使用Java开发Web服务的技术,统称为JavaWeb. B/S与C/S模式 B/S:Browser/Server 浏览器/服务器模式 用户只需要一个浏览器即可访问服务器 C/S:Cl ...

  7. 华清远见-重庆中心-框架技术总结

    框架是一套规范. 实际是他人实现的一系列接口和类的集合.通过导入对应框架的jar文件(Maven项目导入对应的依赖),进行适当的配置,就能使用其中的所有内容.开发者可以省去很多模板代码 Spring ...

  8. 华清远见-重庆中心-JAVA面向对象阶段技术总结

    华清远见-重庆中心-JAVA面向对象阶段技术总结 面向对象和面向过程的编程思想 面向对象(OOP) 通过创建(new)对象,赋予对象对应的行为和特征,让这些对象相互配合来解决问题 面向过程(POP) ...

  9. 华清远见-重庆中心-JAVA基础阶段技术总结

    系列文章目录 第一章 华清远见--重庆中心-JAVA基础阶段技术总结 第二章 文章目录 系列文章目录 文章目录 前言 一.关于java 1.发展历程 2.编程开发 3.java架构 4.java的特点 ...

最新文章

  1. ​防火墙(一)主机型防火墙
  2. html中的插入特殊符号的方法,在Word2016中插入特殊符号的方法
  3. JOGL - Java与OpenGl的绑定(转)
  4. 分布式系统中的限流与熔断
  5. 物理化学 化学 动力学(上)
  6. JAVA常见算法题(三十三)---求子串在字符串中出现的次数
  7. Axure RP Extension for Chrome经常损坏
  8. 对象的List成员添加元素
  9. thoughtworks面试题分析与解答
  10. eclipse安装M2Eclipse插件
  11. Amaze UI后台管理模板 v2.7.2
  12. ctf题库--天下武功唯快不破
  13. 地下城与勇士正在自动连接频道服务器,自动连接频道失败 无限自动连接如何处理...
  14. learn.log - 进程管理器fastcgi原理及fastcgi_param详解
  15. 用python完成选股策略a股_Python 金融: 0亏损选股策略
  16. Android之Manifest文件
  17. lisp获取qleader端点_中文版AutoCAD2013高手之道
  18. 荣耀play4t能升级鸿蒙吗,荣耀30 Pro已开始测试华为鸿蒙HarmonyOS 2.0 荣耀Play4 Pro下月升级...
  19. 回收站清空的文件怎么恢复?
  20. 软考-软件设计师 笔记九(多媒体基础)

热门文章

  1. SEO辅助工具大全,让网站优化事半功
  2. 别说你只看到庞大的中国来客,CES仍在预言2018年AI加持下的科技圈走势
  3. webdav简介与示例
  4. autoconf 英文手册
  5. android加载字体内存泄露,在Windows GDI中创建和使用字体/避免内存泄漏
  6. 获得用户输入的一段文字,将这些文字进行垂直输出
  7. 给大家介绍一款开源的熟人/陌生人社交平台
  8. django启动https协议
  9. js多线程new worker报错cannot be accessed from origin 问题
  10. 软件测试测试充分性准则,Axiomatic Assessment of Logic Coverage Software Testing Criteria对逻辑覆盖软件测试准则的公理化评估...