目录
类A extends 类B implements 接口A,接口B...
一个类的构造方法的作用是什么?若一个类没有声明构造方法,该程序能正确执行吗 ?为什么?
在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?
方法
方法是定义在类中的一段独立代码,能完成某个事情
定义方法时,提供方法的名称、返回值类型、参数列表,这三点成为方法的三要素,定义的方法都需要这三部分
当在使用该方法中的代码时,只需通过该方法名调用即可
方法能够减少代码冗余
调用方法
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));//向上取整
System.out.println(Math.floor(3.9));//向下取整
System.out.println(Math.round(-1.5));//四舍五入
System.out.println(Math.random());//[0,1)之间的随机数
System.out.println(Math.sqrt(9));//平方根
System.out.println(Math.cbrt(27));//开立方
System.out.println(Math.pow(2,3));//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方法");
}
}
方法调用总结
调用方式:
通过类名调用
通过对象调用
直接调用
参数:
无参数
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();
t.funB();
}
}
有返回值
Random rd = new Random();
rd.nextInt(10);
自定义方法
方法的三要素:
1.方法名:
使用驼峰命名法
2。方法返回值类型:
如果有返回值,使用Java中的任意数据类型,方法体中使用return关键字返回对应类型的数据
如果没有返回值,使用void关键字
3.方法参数列表:
参数写法:数据类型 形参名,数据类型 形参名
[修饰符] 返回值类型 方法名(参数列表){
方法体;
}
方法的类型
无参数无返回值
void 方法名(){
//方法体
return;//遇到return立即结束方法
}
无参数有返回值
void 方法名(数据类型 形参名,数据类型 形参名){
//方法体
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;
}
注意
有返回值的方法,必须要在方法体中加入return并能够执行,同时要return一个该方法返回值类型 对应的数据。
没有返回值的方法,可以不用加入return关键字。如果加入return关键字,不能跟上数据。
方法中出现return,会立即结束方法。所以return语句之后不能再有代码。
定义方法时的参数称为形式参数,简称形参;调用方法时,实际传递的参数称为实际参数,简称实 参。实参只需保证数据类型和形参相同即可。
编程思想
面向过程编程
Procedure Oriented Programming 简称POP。
是一种基本的编程思想,将一件事情按流程按步骤执行,逻辑清晰。
每一步都是基于上一步的流程去继续实现。
注重于分析问题的步骤。
如果逻辑复杂,如xxx管理系统,使用POP就会变得很麻烦。
C语言就是一门面向过程的编程语言。
面向对象编程
Object Oriented Programming 简称OOP。
是一种编程思想,核心是创建解决问题的对象,赋予对象行为和特征,让这些对象互相配合执行。
每个对象的行为实际也是面向过程的。
注重于全局如何创建完成某件事情的对象,如果适时地调用。
这种思想致力于将计算机中的世界,描述的和现实中一致的思想。
总结
面向过程:亲力亲为,侧重于分析完成事情的过程
面向对象:所有事情交给相应的对象完成,侧重于如何创建解决问题的对象
类和对象
类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();
}
}
类和对象的关系
对象是类的具体表现,类是对象的模板。
如制作月饼的模具就是一个类,每次用这个模具创建出来的月饼就是一个对象。
先定义类,才能通过该类获取对象。
成员变量和局部变量
成员变量
定义在类中的变量,称为成员变量,有默认值。
整数类型 | 默认值 |
整型 | 0 |
浮点型 | 0.0 |
布尔型 | false |
引用类型(类、数组、接口) | null |
class Person{
String name;//成员变量,String是类类型,属于引用类型,默认为null
int age;//整型,默认0
double[] list;
void fun(){
System.out.println(name);//这里能通过编译,可以使用name,输出null
System.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;
}
}
特点
- 创建对象时必须通过new配合构造方法
- 构造方法没有返回值部分,名称和类名相同
- 构造方法可以存在多个,但是参数不能相同。这些构造方法之间的关系称为方法重载
- 每个类默认有一个隐藏的无参数的构造方法,方法体中隐含了一句super()。用于创建无参数的对象
- 如果自己写了带参数的构造方法,默认无参数的构造方法就会失效。如果想要同时拥有带参数和不 带参数的构造方法, 就需要再次显式地写出来
- 带参数的构造方法常用于初始化成员变量(给类中的变量赋值)
- 构造方法可以限制创建对象时携带的参数
- 构造方法无法通过"."操作符访问,只能通过new关键字创建对象时调用
IDEA中自动生成构造方法
在类空白处右键generate或快捷键alt+insert
面向对象语言的三大特性--封装
封装
使用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
IDEA中自动使用变量接收对象
在对象后.var或快捷键ctrl+alt+v
public static void main(String[] args) {
//创建对象自动使用变量保存 ctrl + alt + v 或 对象.var
Employee employee = new Employee();
}
Windows中的快捷键
windows + D 进入桌面
windows + E 进入文件资源管理器
Typora中的快捷键
1-6级标题 CTRL + 1~6
加粗 选中文字 CTRL + B
倾斜 选中文字 CTRL + l
倾斜 选中文字 CTRL + U
列表 - 空格 缩进 tab
表格 CTRL + T
整段代码 ```语言
嵌入代码 代码
IDEA中常用快捷键
复制粘贴 CTRL + D
自动接收对象 CTRL + ALT + V
自动生成构造方法等 ALT + Insert
自动调整格式 CTRL + ALT + L
删除整行 CTRL + X
CTRL + Y 可以设置为删除整行或配合撤销(CTRL + Z)恢复
面向对象三大特性--继承
概念
类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"继承"这一个公共类,从而减 少这些类中的冗余代码。
如猫类、狗类都有类型、昵称等属性,也有吃、睡等方法,那就可以定义一个动物类,将这些公共的属 性和方法定义在动物类这个父类中,
再让猫类和狗类这些子类继承动物类。这样就能直接通过子类访问父类中的内容。
特点
- 如果多个类之中有相同的代码,可以将这些代码提取出来到一个公共的类中,这个类就是父类。再 让那些类去extends继承这个父类,那些类就是子类。子类就无需再写重复代码
- 子类中或子类对象可以直接访问父类中非私有(不用private修饰)属性和方法
- 创建子类对象时,会先执行父类中相应的构造方法
- 子类继承父类后,通常会对对父类中的方法进行拓展或覆盖,这称为方法重写。重写后,子类再调 用该方法时,执行的是重写后的内容
- Java中是单继承。一个子类只能extends一个父类,一个父类可以有很多子类
- Java中可以多重继承,类A可以继承类B,类B继承类C,这是类A既是类B的子类,也是类C的子 类,类A可以访问类B和类C中的非私有成员
- 任何类都是Object类的子类
方法重写和方法重载
方法重写override
当子类继承父类后,可以对父类中的方法进行扩展或覆盖。这个过程称为方法重写。
方法重写要求
- 方法名、返回值、参数列表必须和父类一致
- 访问权限不能比父类更严格(访问修饰符的范围要么一致要么更大)
- 不能抛出比父类更大的异常
IDEA中如果要重写方法,使用CTRL + O在弹出的窗口中选择要重写的方法
方法重载overload
在一个类中,如果多个方法的方法名相同,参数列表不同时,这些方法称为重载的方法。
同名不同参。
重载用于,在一个类中,某个方法在不同的条件下,执行不同的内容。
方法重载要求
- 方法名相同
- 参数必须不同(数量、类型)
- 与返回值无关
this和super关键字
这两个关键字,都可以当做对象使用,也可当做构造方法使用。
当做对象使用
用法:this.属性或this.方法,super.属性或super.方法
此时的this表示当前类的对象,super表示当前类的父类对象
class Person{
private String name;
public void setName(String name){
//这里的this表示当前类的对象Person对象
//相当于Person p = new Person();中的p
this.name=name;
}
public String getName(){
return name;
}
}
class Man extends Person{
void fun(){
//这里的super表示当前类的父类对象
//Person p = new Person();
//super表示上句话中的p
System.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
通过包可以将.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方法进行重写
@Override
public void fun(){
}
}
修饰类
当final修饰类时,该类不能被继承。
定义类,在class前加final
public final class Father{
public final void fun(){
}
}
//会报错,提示该类无法继承Father
public class Son extends Father{
}
创建对象时的内存变化
Object类
是java中所有类的父类。每个类都是这个类的子类,但没有使用extends体现出来
该类中定义了很多方法,通常需要进行重写。
常用方法 | 返回值 | 作用 |
toString() | String | 在输出某个对象时,会默认调用该方法。该方法默认输出"包名. 类名@十六进制哈希码"。通常用于重写后输出对象的属性。 |
equals(Object obj) | boolean | 判断两个对象是否相同。Object类中默认使用==比较,通常需要 重写该方法,自定义比较的规则。 |
hashcode() | int | 得到对象的哈希码。哈希码可以理解为对象的内存地址,经过一 个特定的算法得到的一个特定值。 |
getClass() | Class | 得到某个对象所在的类。 |
notify() | void | 唤醒某个线程 |
notifyAll() | void | 唤醒所有线程 |
wait(long time) | void | 让线程休眠,直到被唤醒 |
finallize() | void | 当某个对象被垃圾回收机制GC回收前执行的方法 |
对象造型/对象转型/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()可以删除。
Manager类
package com.hqyj.test3;
import java.util.Objects;
/*
* 登录系统的管理员类
* 属性
* 账号
* 密码
* 方法
* 全参构造
* 无参构造
* getter/setter
* toString
* equals
* */
public class Manager {
private String username;
private String password;
@Override
public String toString() {
return "Manager{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
//判断是否是同一个对象
if (this == o) return true;
//是否为空,是否属于同一种类
if (o == null || getClass() != o.getClass()) return false;
//向下转型
Manager manager = (Manager) o;
//遍历所有属性判断是否一致
//Objects是一个工具类,equals()方法判断两个参数是否相同,实际使用参数的equlas方法判
断
return Objects.equals(username, manager.username) &&
Objects.equals(password, manager.password);
}
public Manager() {
}
public Manager(String username, String password) {
this.username = username;
this.password = password;
}
public String getUserna