面向对象基础部分
概要
学习该视频的目的
由于一年前的时候在课上学过java语言,现在大部分知识都忘的差不多了,同时之后学过python和c++等语言.所以前面的语言基础部分就直接跳过了.就直接从面向对象开始看起.
本视频的范围
本部分对应的视频是p178集到p1405集,其中跳过了项目二,其它的都跟着写了一遍,在写的过程通过idea中的git和github对代码进行管理.由于在看的过程中还要上课,一般都是晚上开始开,花了差不多七个晚上的时间将知识过了变.
代码线上地址
想法
可以说收获还是挺大的.首先解除了在学习javaWeb的过程中遇到的一些疑惑.同时对于一些个人认为重要的知识做了标注.对于值得反复看的也做了标注.还有就是一些地方可以会有一些小的疑惑.希望以后可以慢慢的明白.
希望自己可以专精一门语言,那就是java
计划
看完之后,再看java编程思想
该视频的地址
尚硅谷Java入门视频教程(在线答疑+Java面试真题)
第一天
学习面向对象的三条主线
- java类及类的成员
- 面向对象的三大特征
- 其它的关键字
1.体会面向对象
package com.hxut.java;
/**类和对象的使用(面向对象的实现)
*
* 如果修改一个对象不不影响另外一个对象的属性值
* @author weijiangquan
* @date 2022/4/16 -15:31
*/
public class PersonTest{
public static void main(String[] args) {
//创建Person类的对象
Person p1 = new Person();
p1.name = "Tom";
p1.age = 22;
System.out.println(p1.name);
p1.eat();
p1.sleep();
Person p2 = new Person();
System.out.println(p2.name); //null
//将p1变量保存的对象地址赋值给p3,导致p3和p1指向了堆空间的同一个对象实体
Person p3 = p1;
// 修改p3就相当与修改了p1
p3.age = 10;
System.out.println(p3.age); //run result=>10
System.out.println(p1.age); //run result=>10
}
}
// 一.设计类的成员
class Person{
// 属性
String name;
int age;
boolean isMale;
// 方法
public void eat(){
System.out.println("eat");
}
public void sleep(){
System.out.println("睡觉");
}
}
2 对象数组(192集-193集重要)
对象数组的内存解析
- 引用类型的变量,只可能存储量类值:null 或地址(含变量的类型)
package com.hxut.exer;
/**
* 4.对象数组
* 定义学生类Student,包含三个属性 :学号 number(int) 年级 state(int) 成绩score(int)
* 创建20个学生对象,学号为1到20,年级和成绩都由随机数确定
* 问题一:打印3年级(state值为3)的学生信息
* 问题2:使用冒泡排序按学生成绩排序,并遍历所有学生信息
*
* @author weijiangquan
* @date 2022/4/16 -21:09
*/
public class StudentTest{
public static void main(String[] args) {
// 声明一个Student类型的数组
Student[] stus= new Student[20]; //对象数组(这个只是定义了一个数组)
for (int i = 0;i<stus.length;i++){
//给数组元素赋值
stus[i] = new Student(); //给数组的每一个位置new一个对象
//给student对象的属性赋值
stus[i].number = i+1;
//年级是[1,6]闭区间的画 公式(Math.random()*(b-a+1)+a)(记住公式就可以了)
stus[i].state = (int)(Math.random()*(6-1+1)+1);
//成绩:[0-100]
stus[i].score = (int)(Math.random()*(100-0+1));
}
// 遍历一下学生数组
for (Student value : stus) {
// System.out.println(stus[i]);//run result=>com.hxut.exer.Student@4554617c(输出的是地址值)
// ① 用这种(方式一)
// System.out.println(stus[i].number+","+stus[i].state+","+stus[i].score);
// ②用这种调用对象中的方法(方式二)
System.out.println(value.info());
}
System.out.println("=============================");
// 问题1: 打印3年级(state值为3)的学生信息
for (Student student : stus) {
if (student.state == 3) {
System.out.println(student.info());
}
}
System.out.println("=============================");
// 问题2:使用冒泡排序按学生成绩排序,并遍历所有学生信息
for (int i = 0;i<stus.length;i++){
for (int j =0;j<stus.length-1-i;j++){
if(stus[j].score >= stus[j+1].score){
// 如果需要换序,交换的是数组的元素:Student对象
Student temp = stus[j];
stus[j] = stus[j+1];
stus[j+1] = temp;
}
}
}
// 遍历学生数组
for (Student student : stus) {
System.out.println(student.info());
}
}
}
class Student{
int number; //学号
int state; //年级
int score; //成绩
// 显示学生信息的方法
public String info(){
return "学号"+number+",年级"+state+",成绩"+score;
}
}
注意
对于对象数组,我之前在javaweb的时候获取数据库的信息存放在集合中的时候.以为只能存放对象的属性,之前其实是理解上的错误,对象数组中其实存放的是每一个对象的地址,通过地址可以获取该对象的每一个属性(成员属性和成员方法)
拆解分析(myself)
package firstDay;
import java.util.Arrays;
/**
* @author weijiangquan
* @date 2022/4/30 -10:36
* @Description
*/
public class StudentTest{
public static void main(String[] args) {
// 声明一个Student类型的数组
Student[] stus= new Student[2];
Student student = new Student();
student.number = 12;
student.state = 1;
student.score = 150;
stus[0] = student;
Student student1 = new Student();
student1.number = 12;
student1.state = 1;
student1.score = 150;
stus[1] = student1;
// 下面打印地址可以知道对象数组的地址和数组元素的第一个元素的地址是不一样
// 在普通的数组中就是数组的首地址
System.out.println("整个数组地址"+stus); //run result=>整个数组地址[LfirstDay.Student;@1b6d3586
System.out.println("数组中第一个对象元素的地址:"+student); //run result=>数组中第一个对象元素的地址:firstDay.Student@4554617c
System.out.println("掉用toString方法之后:"+Arrays.toString(stus));//run result=>掉用toString方法之后:[firstDay.Student@4554617c, firstDay.Student@74a14482]
// 获取数组某一个对象的属性(私有的不能获取)
//获取成员属性
int number = stus[0].number;
int score = stus[0].score;
//获取成员方法
String info = stus[0].info();
System.out.println("number="+number+"\t"+"score="+score+"\tinfo:"+info);
//run result=>number=12 score=150 info:学号12,年级1,成绩150
}
}
class Student{
int number; //学号
int state; //年级
int score; //成绩
// 显示学生信息的方法
public String info(){
return "学号"+number+",年级"+state+",成绩"+score;
}
}
3.对象的内存图
package com.hxut.java;
/**
* @author weijiangquan
* @date 2022/4/16 -23:11
*/
public class Car {
String color = "red";
int num = 4;
void show(){
int a = 10;//局部变量在栈中
System.out.println("color="+color+","+"num="+num);
}
}
class CarTest{
public static void main(String[] args) {
Car c1 = new Car();
Car c2 = new Car();
c1.color = "blue";
c1.show();
c2.show();
}
}
对于对象new出来之后放在一个变量中的是一个地址
public class InstanceTest_1{
public static void main(String[] args) {
Phone p =new Phone();
System.out.println(p); //run result=>com.hxut09.Phone@1b6d3586(输出的对象的地址)
}
}
class Phone{
}
在本节中有提到局部变量,后面会详细讲解局部变量和成员变量的区别
4. 匿名对象的使用(了解)
package com.hxut09;
/**
*
*
* @author weijiangquan
* @date 2022/4/16 -23:50
*
*
* 一.理解"万事万物皆对象"
* 1.在java语言范畴中,我们都将功能,结构等封装到类中,通过类的实例化,来调用具体的功能结构
* 2.涉及到Java语言与前端Html,后端的数据交互时,前后端的结构java交互时
*
*
* 二.匿名对象的使用
* 1.理解:我们创建的对象:没有显式的赋给一个变量名.就是匿名对象
* 2.特征:只能调用一次
*/
public class InstanceTest_1{
public static void main(String[] args) {
Phone p =new Phone();
System.out.println(p); //run result=>com.hxut09.Phone@1b6d3586(输出的对象的地址)
p.sendEmail();
p.playGame();
// 匿名对象(下面new了两个对象)
new Phone().sendEmail();
new Phone().playGame();
// 匿名对象的使用
PhoneMall mall = new PhoneMall();
mall.show(p); //可以这样写
mall.show(new Phone()); //开发中这样写会更多
}
}
class PhoneMall{
public void show(Phone phone){
phone.sendEmail();
phone.playGame();
}
}
class Phone{
double price;
public void sendEmail(){
System.out.println("发送邮件");
}
public void playGame(){
System.out.println("玩游戏");
}
}
本机中主要知道:在开发中主要使用下面的方式
mall.show(new Phone()); //开发中这样写会更多
5.自定义数组工具类(202集)–先跳过(19min)
涉及到之前数组的知识(对后面不影响)
6.理解方法的重载
案例代码
package com.hxut09;
/**
* @author weijiangquan
* @date 2022/4/17 -0:25
*
*
* 重载
* 1. 允许一个以上的同名方法
* 两同一不同 同一个类 相同的方法名
* 参数列表不同:参数个数不同,参数类型不同
*
* 2.判断是否重载:
* 和方法的权限修饰符,返回值类型,形参变量名,方法体都没有关系
* 3.在通过对象调用方法时,如何确定指定的方法:
* 方法名--->参数列表
*
*/
public class OverLoadTest_2 {
public static void main(String[] args) {
OverLoadTest_2 test_2 = new OverLoadTest_2();
test_2.getSum(1,2);
test_2.getSum("hh",22);
}
public void getSum(int i,int j){
System.out.println(i+j);
}
public void getSum(double i,double j){
System.out.println(i-j);
}
public void getSum(String s,int i){
System.out.println(s+i);
}
// 下面的这个不行
/*public int getSum(int i,int j){
}*/
}
注意:
判断是否重载的时候为什么和返回值类型没有关系:
因为一个类中如果有两方法,其它都一样,救返回类型不一样的话,编译器就会报错,因为> 如果外部调用的话,不知道到底调用哪一个方法
知识忙区
可变形参(操作数据库的时候会用到)
package com.hxut09.exer;
/**
* @author weijiangquan
* @date 2022/4/17 -0:50
*
*
*
* 可变个数形参方法
*
* 1.JDK 5.0新增
* 2.具体使用
* 2.1 可变个数形参的格式 数据类型...变量名
* 2.2 当调用可变个数形参的方法时 传入个数可以是[0,多个)
* 2.3 优先考虑的是不可变参数的(注意)
* 2.4 可变个数形参的方法名与本类中的方法名相同,形参不同的方法之间构成重载
* 2.4 和数组之间不能共存(见下面的例子)---这个比数组更方便
* 2.5 可变要放在参数的最后面
* 2.6 可变个数形参在方法形参中,最多只能声明一个可变形参
*/
public class OverloadExer{
public static void main(String[] args) {
OverloadExer test = new OverloadExer();
test.show(12);
test.show("hello"); //run result=>show(String)
test.show("hello","heslajk");
test.show();
}
public void show(int i){
}
public void show(String s){
System.out.println("show(String)");
}
public void show(String ... strs){
System.out.println("show(String ... strs)");
/*for (int i = 0;i<strs.length;i++){
System.out.println(strs[i]);
}*/
// 和上面for循环等价
for (String str : strs) {
System.out.println(str);
}
}
// 下面会报错
/*public void show(String ... strs,int a){
}*/
// 和上面不能共存
/* public void show(String[] strs){
}*/
}
第二天
7 .值传递机制
理解变量的赋值
package com.hxut09;
/**
* @author weijiangquan
* @date 2022/4/17 -1:24
*
*
* 关于变量的赋值
* 如果变量是基本数据类型:此时赋值的是变量所保存的数据值
* 引用的话,就是地址值了
*/
public class ValueTransferTest_3 {
public static void main(String[] args) {
System.out.println("========基本数据类型=======");
int m = 10; //局部变量
int n = m;
System.out.println("m="+m+",n="+n);
n = 20;
System.out.println("m="+m+",n="+n);
System.out.println("========引用数据类型=======");
Order o1 = new Order();
o1.orderId = 1001;
Order o2 = o1; //赋值以后o1和o2的地址值相同,都指向了堆空间中的同一个对象实体
System.out.println("o1.orderId="+o1.orderId+","+"o1.orderId="+o2.orderId);//run result=>o1.orderId=1001,o1.orderId=1001
o2.orderId = 1002;
System.out.println("o1.orderId="+o1.orderId+","+"o1.orderId="+o2.orderId);//run result=>o1.orderId=1002,o1.orderId=1002
}
}
class Order{
int orderId;
}
值传递机制(基本数据类型)
package secondDay;
/**
* @author weijiangquan
* @date 2022/4/30 -11:14
* @Description
*/
public class ValueTransferTest_3_1 {
public static void main(String[] args) {
// 交换变量
int m = 10;
int n = 20;
ValueTransferTest_3_1 test_3_1 = new ValueTransferTest_3_1();
test_3_1.swap(m,n); //这个时候不会改变值(传进去的只是数据)
System.out.println("m="+m+",n="+n); //run result=>m=10,n=20
}
/**
* 交换两个变量的值操作
* @param m
* @param n
*/
public void swap(int m,int n){
int temp = m;
m = n;
n = temp;
}
}
值传递机制(针对引用引用数据类型)
package com.hxut09.java;
/**
* @author weijiangquan
* @date 2022/4/17 -10:52
*
*
*
* 2.值传递机制
* 如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值
* 如果参数是引用数据类型,此时实参赋给形参的是实参存储数据的地址值
*
*/
public class ValueTransferTest2{
public static void main(String[] args) {
Data data = new Data();
data.m =10;
data.n = 20;
System.out.println("m="+data.m+"n="+data.n);
// 交换m和n的值
/*int temp = data.m;
data.m = data.n;
data.n =data.m;*/ //run result=>交换成功
ValueTransferTest2 test2 = new ValueTransferTest2();
test2.swap(data); //传的是堆空间的同一个对象
System.out.println("m="+data.m+"n="+data.n); //run result=>交换成功
}
public void swap(Data data){
//传的是堆空间的同一个对象Data data = data; 对象传值传的是指针
int temp = data.m;
data.m = data.n;
data.n =data.m;
}
}
class Data{
int m;
int n;
}
值传递机制的练习(p211重要-13min)
练习4
画下面代码的内存图
package com.hxut09.java;
/**
* @author weijiangquan
* @date 2022/4/17 -11:16
*
* 画内存结构图
*/
public class TransferTest3 {
public static void main(String[] args) {
TransferTest3 test3 = new TransferTest3();
test3.first();
}
public void first(){
int i = 5;
Value v = new Value();
v.i = 25;
second(v,i);
System.out.println(v.i);
}
public void second(Value v,int i){
i = 0;
v.i = 20;
Value val = new Value();
v = val;
System.out.println(v.i+""+i);
}
}
class Value{
int i = 15;
}
练习5(面试题)
题目一
package com.hxut09.java;
/**
* @author weijiangquan
* @date 2022/4/17 -11:39
*/
public class ValueTransferTest3 {
public static void main(String[] args) {
int a = 10;
int b = 20;
method(a,b); //需要在method方法被调用后,仅打印处a=100,b=200,写出method方法
System.out.println("a="+a);
System.out.println("b="+b);
}
}
答案
package com.hxut09.java;
/**
* @author weijiangquan
* @date 2022/4/17 -11:39
*/
public class ValueTransferTest3 {
public static void main(String[] args) {
int a = 10;
int b = 20;
method(a,b); //需要在method方法被调用后,仅打印处a=100,b=200,写出method方法
System.out.println("a="+a);
System.out.println("b="+b);
}
public static void method(int a,int b){
System.out.println("a="+a*10);
System.out.println("b="+b*10);
System.exit(0); //退出程序
}
}
题目二
/**
* @author weijiangquan
* @date 2022/4/17 -11:53
* 定义一个整型的数组int型:int[] arr = new int[]{12,3,3,34,56,77,432};
* 让数组的每个位置的值去除以首位置的元素,得到结果,作为该位置上的新值.遍历新的数组
*/
public class Array {
public static void main(String[] args) {
int[] arr = new int[]{
12,3,3,34,56,77,432};
/*// 方法一
for(int i = arr.length-1;i>0;i--){
arr[i] = arr[i]/arr[0];
}*/
// 方法二
int temp = arr[0];
for(int i =0;i<arr.length;i++){
arr[i]=arr[i]/temp;
}
}
}
练习六
package com.hxut09.exer;
/**
* @author weijiangquan
* @date 2022/4/17 -12:09
*/
public class PassObject {
public static void main(String[] args) {
PassObject test = new PassObject();
Circle c= new Circle();
test.printAreass(c,9);
System.out.println("now radius is"+c.radius);
}
public void printAreass(Circle c,int time){
System.out.println("Radius\t\tArea");
//设置圆的半径
for (int i =1;i<=time;i++){
c.radius = i;
System.out.println(c.radius+"\t\t"+c.findArea());
}
c.radius = time+1;
}
}
8.递归方法的使用(了解)(p216-p217)
先跳过
p218是总结
总结
内存结构:栈(局部变量),堆(new出来的结构:对象(成员变量),数组)
成员变量vs局部变量 (方法内,方法形参,构造器内,构造器形参,代码块内)
p219是复习(15min)
p220复习(18min)
9.封装性的引入
------高内聚,低耦合
封装性的初始
package com.hxut10.java;
/**
* @author weijiangquan
* @date 2022/4/17 -14:11
*
*
* 面向对象的特征:封装和隐藏
*
* 一:问题的引入:
* 当我们创建一个类的对象以后,我们可以通过"对象.属性"的方式,对对象进行赋值
* 我们要加入额外的限制条件.通过方法进行限制,避免用户直接访问(程序员),我们可以将属性设成private,这个时候属性就是封装性了
*
* 二:封装性的体现
* 属性的私有化 提供get和set的方法给外部
* 这个是封装性的体现不等于封装(这个只是其中的一个)
*
* 体现有很多
* ①上面 ②私有方法 ③单例模式(后面会提到) ...
*
* 三.封装性的体现 需要权限修饰符
* 1.java规定的4种权限(小->大) private 缺省(默认)protected public(后面会讲)
*
*/
public class AnimalTest {
public static void main(String[] args) {
Animal a = new Animal();
// a.name = "大大";
// a.age =21;
// a.legs = 4;
a.show();
a.eat();
}
}
class Animal{
private String name;
private int age;
private int legs; //退的个数
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
// 设置属性
public void setLegs(int le){
if(le>0&&le%2==0){
legs = le;
}else {
legs =0;
}
}
//获取属性
public int getLegs(){
return legs;
}
public void eat(){
System.out.println("动物吃饭");
}
public void show(){
System.out.println(name+age+legs);
}
}
四种权限修饰符的理解(重要)
修饰符 | 类内部 | 同一个包 | 不同包子类 | 同一个工程 |
---|---|---|---|---|
private | yes | |||
(缺省) | yes | yes | ||
protected | yes | yes | yes | |
public | yes | yes | yes | yes |
封装性的体现 需要权限修饰符
- java规定的4种权限(小->大): private 缺省(默认)protected public
- 四种权限可以修饰类及类的内部结构:属性,方法,构造器,内部类
- 注意修饰类的话,只能使用:
缺省
,public
- 这个体现及类内部封装性的
10 构造器的引用
11.javaBean,是一种java语言写成的可重用组件
所谓javaBean,是指符合如下标准的java类:
- 类是公共的
- 有一个无参的公共的构造器
- 有属性,且有对应的get,set方法
用户可以通过使用javaBean将功能,处理,值,数据库访问和其它任何可以用
java代码创造的对象进行打包,并且其它的开发者可以通过内部的JSP页面,servlet,其它javaBean,apple程序或者应用来使用这些对象.用户可以认为javaBean提供了一种随时随地的赋值和粘贴的功能,而不用关心任何改变.
12 this的使用
package com.hxut10.java2;
/**
* @author weijiangquan
* @date 2022/4/17 -20:02
*
* this关键字的使用
* 1.this可以用来修饰:属性,方法,构造器
* 2.this修饰属性和方法
* this理解为当前对象或当前正在创建的对象
* 2.1 在类的方法中 我们可以使用"this.属性或this.方法"的方式调用当前对象属性或方法.但是,通常
* 情况下,我们都选择省略"this.变量"的方式,表明此变量是属性而不是形参
* 2.2 在类的构造器中 我们可以使用"this.属性或this.方法"的方式调用当前对象属性或方法.但是,通常
* 情况下, 我们都选择省略"this.变量"的方式,表明此变量是属性而不是形参'
*
* 3.this调用构造器
* ① 在类的构造器中,可以显式的使用"this(形参列表)"方式,调用本类中指定的其它构造器
* ② 构造器中不能使用"this(形参列表)"调用自己
* ③ 如果一个类中有n个构造器,就最多有n-1构造器中使用了"this(形参列表)"
* ④ 规定""this(形参列表)""必须声明在当前构造器的首行
* ⑤ 构造器的内部,最多只能声明一个"this(形参列表)",用来调用其它的构造器(细节问题)
*
*
*
*/
public class PersonTest {
public static void main(String[] args) {
Person person = new Person();
person.setAge(121);
System.out.println(person.getAge());
}
}
class Person{
private String name;
private int age;
public Person(){
this.eat();
}
public Person(String name){
this(); //调用无参
this.name = name;
}
private void eat() {
System.out.println("吃饭");
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age; //this是当前的对象
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
}
13 综合练习1(重要,适合反复练习p215-p216)
通过本案例可以更加的熟悉对象类型的使用
package com.hxut10.exer3;
/**
* @author weijiangquan
* @date 2022/4/17 -21:59
* 题目要求测试程序
* (1)创建一个Customer,名字叫Jane Smith,他有一个账号为1000,余额为2000元,年
* 利率为1.23%的账户
* (2) 对Jane Smith操作
*
* 存入100元,再取出960元,再取出2000元
* 打印出Jane Smith的基本信息
*
* 成功存入 100.0
* 成功取出 960.0
* 余额不足:取款失败
*
*/
public class CustomerTest {
public static void main(String[] args) {
Customer customer = new Customer("Jane","Smith");
Account account = new Account(1000,2000,0.0123);
customer.setAccount(account);
customer.getAccount().deposit(100);
customer.getAccount().withDraw(960);
customer.getAccount().withDraw(2000);
System.out.println("Custormer["+customer.getLastName()+","+customer.getFirstName()+"] has a accout:id is"
+customer.getAccount().getId()+","+",annualINteresRate is"+customer.getAccount().getAnnualInterestRate()*100
+"%,balance is"+customer.getAccount().getBalance());
}
}
package com.hxut10.exer3;
/**
* @author weijiangquan
* @date 2022/4/17 -21:55
*/
public class Customer {
private String firstName;
private String lastName;
private Account account; //定义引用类型 (情感上接收一下)想象成String类型就可以了
public Customer(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
}
package com.hxut10.exer3;
/**
* @author weijiangquan
* @date 2022/4/17 -21:48
*/
public class Account {
private int id; //账号
private double balance; //余额
private double annualInterestRate; //年利率
public Account(int id, double balance, double annualInterestRate) {
this.id = id;
this.balance = balance;
this.annualInterestRate = annualInterestRate;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public double getAnnualInterestRate() {
return annualInterestRate;
}
public void setAnnualInterestRate(double annualInterestRate) {
this.annualInterestRate = annualInterestRate;
}
/**
* 取钱
* @param amount
*/
public void withDraw(double amount){
if(balance < amount){
System.out.println("余额不足,取钱失败");
return;
}
balance -= amount;
System.out.println("取钱成功"+amount);
}
/**
* 存钱
* @param amount
*/
public void deposit(double amount){
if(amount>0){
balance+=amount;
System.out.println("成功存入"+amount);
}
}
}
第一次重做
为了方便,我江三个类写在了一个文件中
package secondDay.exer3;
/**
* @author weijiangquan
* @date 2022/4/30 -11:45
* @Description
*/
/**
* 测试类
*/
public class CustomerTest{
public static void main(String[] args) {
Customer customer = new Customer("wei","fei");
Account account = new Account(12,100,0.1);
customer.setAccount(account);
// 取钱
System.out.print(customer.getName()+"用户:");
customer.getAccount().withDraw(45);
customer.getAccount().deposit(121);
}
}
/**
* 用户类(在用户类中使用了账号类)
*/
class Customer{
private String firstName;
private String lastName;
private Account account;
public String getName(){
return firstName+lastName;
}
/**
* 构造器
*/
//***********************start**************************************
public Customer(String firstName,String lastName){
this.firstName = firstName;
this.lastName = lastName;
}
//*****************************end**********************************
/**
* get方法
* FirstName,LastName通过构造器改变,没有写set方法
*
*/
//***********************start**************************************
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
//*****************************end**********************************
}
/**
* 账号类
*/
class Account{
private int id; //账号
private double balance;//余额
private double annualInterestRate; //年利率
/**
* 取钱
* @param amount 要取的钱的多少
*/
public void withDraw(double amount){
if(balance < amount){
System.out.println("余额不足,取钱失败");
return;
}
balance -= amount;
System.out.println("取钱成功"+amount);
System.out.println("还有余额"+balance);
}
public void deposit(double amount){
if(amount > 0){
balance+=amount;
System.out.println("成功存入:"+amount);
System.out.println("还有余额:"+balance);
}
}
/**
* 构造器
*/
//***********************start**************************************
public Account(int id, double balance, double annualInterestRate) {
this.id = id;
this.balance = balance;
this.annualInterestRate = annualInterestRate;
}
//*****************************end**********************************
/**
* set和get方法
*/
//***********************start**************************************
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public double getAnnualInterestRate() {
return annualInterestRate;
}
public void setAnnualInterestRate(double annualInterestRate) {
this.annualInterestRate = annualInterestRate;
}
//*****************************end**********************************
}
本次重写的收获
更加清楚了两个不相关的类是如何建立连接的
知道了为什么要写成两个类,本来一个类也是可以完成的,两个类的话,让结构更加的清晰
14 综合练习2(对象数组-p237-适合重复看)
package com.hxut10.exer4;
/**
* @author weijiangquan
* @date 2022/4/18 -0:31
*
* 对象数组(银行相关的相对于上一个例子更复杂一点)
*/
public class BankTest {
public static void main(String[] args) {
Bank bank = new Bank();
bank.addCustomer("jane","Smith");
bank.getCustomer(0).setAccount(new Account(2000));
bank.getCustomer(0).getAccount().withDraw(500);
double balance = bank.getCustomer(0).getAccount().getBalance();
System.out.println("客户"+bank.getCustomer(0).getFirstName()+"账户余额为:"+balance);
System.out.println("****************************");
bank.addCustomer("万里","杨");
System.out.println("银行各户的个数为"+bank.getNumOfCustomers());
}
}
package com.hxut10.exer4;
/**
* @author weijiangquan
* @date 2022/4/18 -0:18
*/
public class Bank {
private Customer[] customers; //存放多个用户的数组
private int numberOfCustomers; //记录客户的个数
public Bank(){
customers = new Customer[10]; //创建一个数组
}
/**
* 添加用户
* @param f
* @param l
*/
public void addCustomer(String f,String l){
Customer customer = new Customer(f,l);
/*customers[numberOfCustomers] = customer;
numberOfCustomers++;*/
// 将上面的代码合并一下
customers[numberOfCustomers++] = customer; //放在数组中
}
/**
* 获取用户的个数
* @return
*/
public int getNumOfCustomers(){
return numberOfCustomers;
}
/**
* 获取指定位置上的客户
* @param index
* @return
*/
public Customer getCustomer(int index){
if(index>=0&&index<numberOfCustomers){
return customers[index];
}
return null;
}
}
package com.hxut10.exer4;
/**
* @author weijiangquan
* @date 2022/4/18 -0:16
*/
public class Customer {
private String firstName;
private String lastName;
private Account account;
public Customer(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
}
package com.hxut10.exer4;
/**
* @author weijiangquan
* @date 2022/4/18 -0:11
*
* 综合练习2 p237
*
*/
public class Account {
private double balance;
public Account(double init_balance){
this.balance = init_balance;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
/**
* 存钱
* @param amt
*/
public void deposit(double amt){
if(amt>0){
balance+=amt;
System.out.println("存钱成功");
}
}
public void withDraw(double amt){
if(balance >= amt){
balance -= amt;
System.out.println("取钱成功");
}else {
System.out.println("取钱失败,余额不足");
}
}
}
15 对象数组的内存图
第三天
1. 项目二(先跳过 p248-p259 p265 p270)
2.继承
2.1继承的理解
继承的好处:
-
提高了复用性,减少代码的冗余.
-
便于功能的扩展
-
为了之后的多态的使用提供了前提
继承的格式:class A extends B{}
(1)体现:一旦继承之后,子类就获取了父类中声明的所有的属性和方法
特别的,父类中声明为private的属性和方法,子类继承以后,仍然认为获取了父类中私有的结构,只是因为封装性的影响,使得子类不能直接调用父类的结构而已(希望以后可以了解源码,看看原理是什么)
(2)子类继承父类以后可以声明自己特有的属性或者方法.使用功能的拓展
子类和父类不同于子集和集合的关系
java中关于继承的规定
- 一个类可以被多个子类继承
- 一个类只能有一个父类(单继承性)
- 子类和父类是相对的概念
- 子类直接继承的父类称为直接父类,间接继承的父类,间接父类
- 子类继承父类后,就获得了直接父类以及所有间接父类中声明的属性和方法
(3)
- 如果没有显式的声明一个类的父类的话,则就继承于java.lang.Object类
- 都有Object的功能(Object的方法也不是很多)
2.2 方法重写的理解
定义:对于继承的方法的改造
* 方法的重写
* 1.重写,子类继承父类后,可以对父类中同名参数的方法,进行覆盖操作
* 2.应用,重写以后,当创建子类的对象以后,通过子类对象调用父类中的同名同参的方法时,实际执行的是子类重写的方法
*
* 3.重写的规定
* 方法的声明:权限修饰符 返回值类型 方法名(形参列表){
* //方法体
* }
* 预定:子类称为重写的方法,父类叫被重写的方法
* ① 子类重写的方法名称和形参列表和父类被重写的相同
* ② 子类重写的方法的权限修饰符不小与父类被重写的权限修饰符
* ->特殊情况,子类不能重写父类中被声明为private权限方法
* ③ 返回值类型
* >父类被重写的方法的返回值类型是void,则子类重写的方法的返回值类型只能是void
* > 父类父类被重写的方法的返回值类型是A类型,则子类重写的方法的返回值类型可以是A类或A类的子类
* > 父类被重写的方法的返回值类型是基本数据类型,则子类重写的方法的返回值类型必须是相同的基本数据类型(注意)
* 比如子类是 double 这个时候父类也是 double
* ④ 异常子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型(到异常处理的时候再说)
* *************************************
* 子类和父类中同名同参数的方法要么都声明为非static,要么都声明为static的.(不是重写)
举例说明
不符合条件
package third;
import org.junit.Test;
/**
* @author weijiangquan
* @date 2022/4/30 -12:32
* @Description
*/
class A{
public static void eat(){
System.out.println("A吃饭");
}
}
public class B extends A{
public void eat() {
//报错喜
System.out.println("B吃饭");
}
@Test
public void test(){
A.eat();
}
}
符合条件
package third;
import org.junit.Test;
/**
* @author weijiangquan
* @date 2022/4/30 -12:32
* @Description
*/
class A{
public static void eat(){
System.out.println("A吃饭");
}
}
public class B extends A{
public static void eat() {
//报错喜
System.out.println("B吃饭");
}
@Test
public void test(){
A.eat();//run result=>A吃饭
B.eat();//run result=>B吃饭
}
}
2.3 测试4种不同的访问权限修饰符
package com.hxut12.java2;
/**
* @author weijiangquan
* @date 2022/4/18 -18:39
*
*
* 体会4种不同的权限修饰符
*
*/
public class Order {
private int orderPrivate;
int orderDefault;
protected int orderProtected;
public int orderPublic;
private void methodPrivate(){
orderPrivate = 11;
orderDefault=2;
orderProtected=3;
orderPublic = 4;
}
void methodDefault(){
}
protected void orderProtected(){
}
public void orderPublic(){
}
}
package com.hxut12.java2;
/**
* @author weijiangquan
* @date 2022/4/18 -19:17
*/
public class OrderTest {
public static void main(String[] args) {
Order order = new Order();
order.orderDefault = 1;
order.orderProtected = 2;
order.orderPublic = 3;
order.methodDefault();
order.orderProtected();
order.orderPublic();
// 下面两个都报错 同一个包种不能调用私有的属性和方法
/*order.orderPrivate = 4;
order.methodPrivate();*/
}
}
2.4 super(不是很熟悉)
案例代码
person是父类,Student是子类
代码案例
package com.hxut12.java2;
/**
* @author weijiangquan
* @date 2022/4/18 -19:29
*/
public class Person {
String name;
int age;
int id = 420; //省份证号
public Person(){
System.out.println("我是Person(父类)");
}
public Person(String name){
this.name = name;
}
public Person(String name,int age){
this(name);
this.age = age;
}
public void eat(){
System.out.println("人,吃饭");
}
public void walk(){
System.out.println("人;走路");
}
}
package com.hxut12.java2;
/**
* @author weijiangquan
* @date 2022/4/18 -19:29
*/
public class Student extends Person{
String major;
int age;
int id = 110; //学号 属性不会被覆盖(注意)
/**
* 默认调用了super()
*/
public Student(){
}
public Student(String major){
this.major = major;
}
public Student(String name,int age,String major){
super(name,age); //调用父类指定参数的构造器
this.major= major;
}
@Override
public void eat(){
System.out.println("学生,多吃有营养的食物");
}
public void study(){
System.out.println("学生,学习知识");
}
public void show(){
System.out.println("name="+this.name+",age="+super.age);
System.out.println("id="+this.id); //run result=>id=110
System.out.println("id="+super.id); //run result=>id=420
}
}
package com.hxut12.java2;
/**
* @author weijiangquan
* @date 2022/4/18 -19:29
*
* super关键字的使用
* 1.super理解为:父类的
* 2.super可以用来调用属性,方法,构造器
*
*
* 3.super的使用
* 3.1 可以在子类的方法构造器中,通过使用"super.属性"或"super.方法"的方式,显式的调用父类中声明的属性或方法
* 但是通常情况下,我们习惯省略"super."
* 3.2 特殊情况:当子类和父类中定义联动同名的属性时,我们想要在子类中调用父类中声明的属性,则必须显式的使用
* "super.属性"的方式.表明是父类中声明的属性
* 3.3 特殊情况:当子类重写了父类的方法后,我们想在子类的方法中调用父类被重写的方法时,则必须显式的使用
* * "super.方法"的方式.表明是父类中声明的方法
*
* 4.super调用构造器
* 4.1 我们可以在子类的构造器中显式的使用"super(形参列表)"的方式,调用父类中声明的指定的构造器
* 4.2 super必须声明在子类构造器的首行
* 4.3 在类的构造器中,针对"this(形参列表)"或"super(形参列表)"只能二选一个不能同时出现
* 4.4 在构造器的首行,没有显式的声明"this(形参列表)"或"super(形参列表)",则默认调用的时父类中空参的构造器:super()
* 4.5 在类的多个构造器中至少有一个类的构造器中使用了"super(形参列表)",调用父类中的构造器
*/
public class SuperTest {
public static void main(String[] args) {
Student student = new Student();
student.show();
Student s1 = new Student("Tom",12,"java高级程序设计");
s1.show();
System.out.println("*************************");
Student s2 = new Student();
}
}
例子代码(super的课后练习–p279)—以后在写
已经看了7分钟了
3 多态(重要)
代码讲解一
package com.hxut12.java3;
/**
* @author weijiangquan
* @date 2022/4/18 -21:12
*
*
* 面向对象的特征三:多态性 (运行时多态 )
*
* 1.理解多态:一个事物的多种形态。
* 2.何为多态性:父类的引用指向子类的对象(或者子类的对象赋给父类的引用)
* 3.多态的使用,虚拟方法的调用
* 有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,
* 但是在执行期,我们实际执行的是子类重写父类的方法
* 总结:编译看左边,运行看右边
*
* 4.多态的使用的前提:①类的继承关系 ②要有方法的重写
*
* 5.对象的多态性:只适用于方法,不适用于属性(编译和运行都看左边)
*
*
* 为什么super(...)或this(...)调用语句只能作为构造器中的第一句出现?
* 答:无论通过哪个构造器继承父类后,继承父类中所有的属性和方法,因此子类有必要知道父类如何为对象进行初始化
*
*
*/
public class PersonTest{
public static void main(String[] args) {
Person p1 = new Person();
p1.eat();
Man man =new Man();
man.eat();
man.age = 25;
man.earnMoney();
System.out.println("***********************");
//***************************************
//对象的多态性 父类的引用指向子类的对象
Person p2 = new Man();
// Person p3 = new Woman();
// 多态的使用,当调用子父类同名的方法时,实际执行的是子类重写父类的方法---虚拟方法调用
p2.eat();
p2.walk();
}
}
package com.hxut12.java3;
/**
* @author weijiangquan
* @date 2022/4/18 -21:07
*/
public class Person{
String name;
int age;
public void eat(){
System.out.println("人吃饭");
}
public void walk(){
System.out.println("人走路");
}
}
package com.hxut12.java3;
/**
* @author weijiangquan
* @date 2022/4/18 -21:08
*/
public class Man extends Person{
boolean isSmoking;
public void earnMoney(){
System.out.println("男人负责赚钱养家");
}
public void eat(){
System.out.println("男人多吃肉,长肌肉");
}
public void walk(){
System.out.println("男人霸气走路");
}
}
package com.hxut12.java3;
/**
* @author weijiangquan
* @date 2022/4/18 -21:10
*/
public class Woman extends Person{
boolean isBeauty;
public void goShopping(){
System.out.println("女人喜欢购物");
}
public void eat(){
System.out.println("女人少吃饭");
}
public void walk(){
System.out.println("女人窈窕的走路");
}
}
代码讲解二(多态的使用)
package com.hxut12.java3;
import java.sql.Connection;
/**
* @author weijiangquan
* @date 2022/4/18 -21:30
*
*
* 多态性的使用举例一:
*
*
*/
public class AnimalTest{
public static void main(String[] args) {
AnimalTest test = new AnimalTest();
test.func(new Dog());
test.func(new Cat());
}
public void func(Animal animal){
animal.eat();
animal.shout();
}
// 如果没有多态的话,就会比较麻烦,要写下面的两个
/*public void func(Dog dog){
dog.eat();
dog.shout();
}
public void func(Cat dog){
dog.eat();
dog.shout();
}*/
}
class Animal{
public void eat(){
System.out.println("动物,进食");
}
public void shout(){
System.out.println("动物:叫");
}
}
class Dog extends Animal{
public void eat(){
System.out.println("狗吃骨头");
}
public void shout(){
System.out.println("汪,汪,汪");
}
}
class Cat extends Animal{
public void eat(){
System.out.println("猫吃鱼");
}
public void shout(){
System.out.println("喵喵");
}
}
// 举例二
class Order{
// 用下面的这个的话就只能调用Object有的方法了?(疑惑)
public void method(Object obj){
}
}
// 举例三
class Driver{
public void doData(Connection conn){
//父类的结构 conn = new MySQLConnection() /conn = new Aracle();
//规范的步骤操作数据
/*conn.method1();
conn.method1();
conn.method1();*/
}
}
第四天
一 多态(重要)
1.向下转型的使用(忘的差不多)(p287)(开发的时候不常用)
在我印象中用的目前自己用的不是很多
man.java(子类)
package com.hxut12.java3;
/**
* @author weijiangquan
* @date 2022/4/18 -21:08
*/
public class Man extends Person{
boolean isSmoking;
int id = 1111;
public void earnMoney(){
System.out.println("男人负责赚钱养家");
}
public void eat(){
System.out.println("男人多吃肉,长肌肉");
}
public void walk(){
System.out.println("男人霸气走路");
}
}
Person.java(父类)
package com.hxut12.java3;
/**
* @author weijiangquan
* @date 2022/4/18 -21:07
*/
public class Person{
String name;
int age;
int id = 1002;
public void eat(){
System.out.println("人吃饭");
}
public void walk(){
System.out.println("人走路");
}
}
//对象的多态性 父类的引用指向子类的对象
Person p2 = new Man();
// Person p3 = new Woman();
// 多态的使用,当调用子父类同名的方法时,实际执行的是子类重写父类的方法---虚拟方法调用
p2.eat();
p2.walk();
System.out.println(p2.id); //1002 调用的是父类属性(前面提到过,属性编译和运行都看左边)
System.out.println("************************************");
// 不能调用子类特有的方法和属性(注意)
p2.isSmoking;//会报错 isSmoking是子类所特有的方法 不能通过父类的引用调用
如上对于isSmoking
这个属性是男人所特有的属性,不能通过父类的引用调用
思考:通过父类的引用指向的子类的对象中有没有子类的特有的属性
那我们如果想要调用IsSmoking这个子类所特有的属性应该怎么办
可以通过下面的图更好的理解向下转型
在没有使用向下转型的时候 打印一下p2的地址
System.out.println("p2的地址"+p2);
// 如何才能调用子类所特有的方法 使用强制类型转换符
Man m1= (Man)p2;
System.out.println(m1.isSmoking);
System.out.println(m1.id);
System.out.println("m1的地址"+m1);
System.out.println("p2的地址"+p2);
也不是说可以随便转的
主意:在强转的时候,可能出现异常
为了避免出现这种情况我们引入了一个关键字
2.instanceof关键字的使用
目前还没有发现这个关键字的特别大的作用
/**
* a instanceof A:判断对象a是否是类A的实例 如果是,返回true,不是就返回false
*
*
* 使用情况:为了避免向下转型时出现CalssCastException的异常,我们在向下转型之前,先进行
* instanceof判断,一旦返回true,就进行向下转型.如果是false就终止.
*
* 如果a instanceof A 返回true,其中类B是类A的父类则a instanceof B也返回的是true
*
*/
if(p2 instanceof Woman){
Woman w1 = (Woman)p2;
w1.goShopping();
System.out.println("*********Woman*********");
}
if(p2 instanceof Man){
Man m2 = (Man)p2;
m2.earnMoney();
System.out.println("**********Man*************");
}
if(p2 instanceof Person){
System.out.println("***********Person********");
}
if(p2 instanceof Object){
System.out.println("*********Object*********");
}
3 向下转型的几个常见问题
// 练习一
// 问题一:编译的时候通过,运行的时候不通过
// 举例一:
Person p3 = new Woman();
Man m3 = (Man)p3;
// 举例二
Person p4 = new Person();
Man m4 = (Man)p4;
//问题二:编译和运行都通过(Object)
Object obj = new Woman();
Person p = (Person)obj;
// 问题三
// 编译不过
// Man m5 = new Woman();
4 多态的练习题一
package com.hxut13.exer;
/**
* @author weijiangquan
* @date 2022/4/25 -17:45
* 若子类重写了父类的方法,就意味着子类里定义的方法彻底覆盖了父类里同名的方法
* 系统将不可能把父类里的方法转移到子类种。 (编译看左,运行看右边)
*
* 对于实例对象不存在这样的现象,即使子类里定义与父类完全相同的实例变量,这个实例变量不可能覆盖父类种的实例对象(编译运行看左边)
* 上面写的有点问题吧
* 一道笔试题
*/
class Base{
int count = 10;
public void display(){
System.out.println(this.count);
}
}
class Sub extends Base{
int count =20;
public void display(){
System.out.println(this.count);
}
}
public class FieldMethodTest {
public static void main(String[] args) {
Sub s = new Sub();
System.out.println(s.count); //20
s.display(); //20
Base b = s;
// == ,对于引用类型来讲,比较的是两个引用数据类型的地址值是否相等(重要)
System.out.println(b==s); //true
System.out.println("b"+b); //bcom.hxut13.exer.Sub@1b6d3586 (有一个小的疑问,这个地址是自己本身的地址,还是堆空间数据的地址)
System.out.println("s"+s); //scom.hxut13.exer.Sub@1b6d3586
System.out.println(b.count); //10 属性编译和运行和都是看的左边
b.display(); //20
}
}
5 多态的练习题二
package com.hxut13.exer;
/**
* @author weijiangquan
* @date 2022/4/25 -18:10
*
*
*
*/
public class InstanceTest {
public static void main(String[] args) {
InstanceTest test = new InstanceTest();
test.method(new Student());
}
public void method(Person e){
//方法调用的时候多态性的使用
//虚拟方法调用
String info = e.getInfo();
System.out.println(info);
// 方法一
if (e instanceof Graduate){
System.out.println("a Graduate student");
System.out.println("a student");
System.out.println("person");
}else if(e instanceof Student){
System.out.println("a student");
System.out.println("person");
}else {
System.out.println("person");
}
// 方法二
/*if(e instanceof Graduate){
System.out.println("a Graduate student");
}
if(e instanceof Student){
System.out.println("a student");
}
if(e instanceof Person){
System.out.println("person");
}*/
}
}
class Person{
protected String name = "person";
protected int age = 50;
public String getInfo(){
return "Name"+name+"\n"+"age"+age;
}
}
class Student extends Person{
protected String school = "pku";
public String getInfo(){
return "Name"+name+"\n"+"age"+age+"\n"+"school"+"\n"+school;
}
}
class Graduate extends Student{
public String major = "IT";
public String getInfo(){
return "Name"+name+"\n"+"age"+age+"\n"+"school"+"\n"+school+"\nmajor"+major;
}
}
6 多态练习题三
一个类有两个子类
父类
package com.hxut13.exer1;
/**
* @author weijiangquan
* @date 2022/4/25 -18:32
*/
public class GeometricObject {
//几何图形
protected java.lang.String color;
protected double weight;
public GeometricObject(String color, double weight) {
this.color = color;
this.weight = weight;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
/**
* 求面积
* @return
*
* 我有一个疑问,这个方法子类自己要重写的(没有子类会用到父类的方法),都用不到父类的,父类还有必要写这个方法吗?
* 想明白了:有必要,而且必须要写,因为对于多态来说,通过父类的引用指向不同的子类的时候,
* 子类必须重写了父类的方法,才可以调用不同子类重写之后的方法
*
* 所以这里返回0.0似乎毫无意义
*/
public double findArea(){
return 0.0;
}
}
子类1
package com.hxut13.exer1;
/**
* @author weijiangquan
* @date 2022/4/25 -18:43
*/
public class Circle extends GeometricObject{
public double radius;
public Circle(double radius,String color, double weight) {
super(color, weight);
this.radius = radius;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
@Override
public double findArea() {
return 3.14*radius;
}
}
子类二
package com.hxut13.exer1;
/**
* @author weijiangquan
* @date 2022/4/25 -18:47
*/
public class MyRectangle extends GeometricObject{
private double width;
private double height;
public MyRectangle(double width,double height,String color, double weight) {
super(color, weight);
this.width = width;
this.height = height;
}
public double getWidth() {
return width;
}
public void setWidth(double width) {
this.width = width;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
@Override
public double findArea() {
return width*height;
}
}
测试类
package com.hxut13.exer1;
/**
* @author weijiangquan
* @date 2022/4/25 -18:50
*
*
*/
public class Test{
public static void main(String[] args) {
Test test = new Test();
// 计算面积
Circle c1 = new Circle(2.3,"white",1.0);
test.displayGeometricObject(c1);
Circle c2 = new Circle(3.3,"white",1.0);
test.displayGeometricObject(c2);
// 判断面积是否相等
boolean isEquals = test.equalsArea(c1,c2);
System.out.println("c1和c2是否相等:"+isEquals);
}
//比较两个图形的面积是否相等
public boolean equalsArea(GeometricObject o1,GeometricObject o2){
return o1.findArea() == o2.findArea();
}
//求面积
public void displayGeometricObject(GeometricObject o){
//多态 在开发中多态被大量的使用
System.out.println("面积为:"+o.findArea());
}
}
运行结果
7 一件豁然开朗的事
这个事建立在前面两个例题的基础上
8 练习题四–重写方法
多态是运行时的行为
package com.hxut13.exer3;
/**
* @author weijiangquan
* @date 2022/4/25 -19:54
*
* 笔试题目(看起来简单 实际上有点难度)
*
* 想一下add是不是重写
*/
public class InterviewTest1 {
public static void main(String[] args) {
Base1 base1 = new Sub1();
base1.add(1,2,3);
Sub1 s = (Sub1)base1; //强转
s.add(1,23,3);
}
}
class Base1{
public void add(int a,int... arr){
//是重写
System.out.println("base1");
}
}
class Sub1 extends Base1{
public void add(int a,int[] arr){
//这个算重写
System.out.println("sub_1");
}
public void add(int a,int b,int c){
System.out.println("sub_2");
}
}
二 object类的使用
程序员可以通过System.gc()通知过来回收垃圾,通知了不一定会立刻来
* @author weijiangquan
* @date 2022/4/25 -20:06
*
* java.lang.Object
* 1.Object类是所有Java类的根父类
* 2.如果在类的声明中未使用extends关键字指明其父类,则默认父类是java.lang.Object
* 3.Object类中的功能(属性和方法具有)通用性
* 属性 :无
* 方法:equals() /toString /getClass() /hashCode() /finalize
* wait() notify() notifyAll()
* 4.Object类只声明了一个空参构造器
9 ==运算符的回顾
package com.hxut13.java2;
/**
* @author weijiangquan
* @date 2022/4/25 -20:35
*
* 面试题: ==和equals的区别
*
* ==:运算符
* 1.可以使用在基本数据类型和引用数据类型变量中
* 2.如果比较的是基本的类型变量:比较的两个变量保存的数据是否相等 (不一定类型要相同)
* 如果比较的是引用雷类型:比较两个对象的地址值是否相同,即两个引用是否指向同一个对象实体
*
*
*/
public class EqualsTest {
public static void main(String[] args) {
int i = 10;
int j = 10;
double d = 10.0;
System.out.println(i==j); //run result=>true
System.out.println(i==d); //run result=>true 会有基本数据类型的提升
boolean b = true;
// System.out.println(i==b); //run result=>报错 都不和布尔类型的完
char c = 10; //这里没有单引号就是10
System.out.println(i==c); //run result=>true
char c1= 'A';
char c2 = 65;
System.out.println(c1==c2);//run result=>true
// 比较引用类型的 Customer是自己定义的是同一类
Customer customer = new Customer("gasjkd",12);
Customer customer1 = new Customer("dsada",121);
System.out.println(c1==c2); //run result=>false
String str1 = new String("asdda");
String str2 = new String("dsadadfaf");
System.out.println(str1==str2);//run result=>false
}
}
package com.hxut13.java2;
/**
* @author weijiangquan
* @date 2022/4/25 -20:43
*/
public class Customer {
private String name;
private int age;
public Customer() {
}
public Customer(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
10 equals方法的使用(这节知识点很重要 p296)
小的技巧
package com.hxut13.java2;
import java.util.Date;
/**
* @author weijiangquan
* @date 2022/4/25 -20:35
*
* 这节课很重要(干货慢慢)
*
* 面试题: ==和equals的区别
*
* 回顾 == 的使用
* ==:运算符
* 1.可以使用在基本数据类型和引用数据类型变量中
* 2.如果比较的是基本的类型变量:比较的两个变量保存的数据是否相等 (不一定类型要相同)
* 如果比较的是引用类型:比较两个对象的地址值是否相同,即两个引用是否指向同一个对象实体
*
* 二.equals()方法的使用
* 1.是一个方法,而非运算符
* 2.适用于引用数据类型
* 3.Object中equals()的定义
* public boolean equals(Object obj) {
* return (this == obj);
* }
* 说明:Object类中定义的equals()和==的作用是相同的
* 4.像 String,date,File,包装类等都重写了Object类中的equals方法 重写以后,比较的不是两个引用的地址是否相同
* 而是比较两个对象的"实体内容"是否相同
*
*
*
*/
public class EqualsTest {
public static void main(String[] args) {
int i = 10;
int j = 10;
double d = 10.0;
System.out.println(i==j); //run result=>true
System.out.println(i==d); //run result=>true 会有基本数据类型的提升
boolean b = true;
// System.out.println(i==b); //run result=>报错 都不和布尔类型的玩
char c = 10; //这里没有单引号就是10
System.out.println(i==c); //run result=>true
char c1= 'A';
char c2 = 65;
System.out.println(c1==c2);//run result=>true
// 比较引用类型的 Customer是自己定义的是同一类
Customer customer = new Customer("aaa",12);
Customer customer1 = new Customer("dsada",121);
System.out.println(c1==c2); //run result=>false
String str1 = new String("aaa");
String str2 = new String("aaa");
System.out.println(str1==str2);//run result=>false
System.out.println(customer.equals(customer1)); //对于equals实际上用到了多态 Object obj
//run result=>false
System.out.println(str1.equals(str2)); //run result=>true
//这里的的equals被重写了和上面的不一样(看看Sring类中equals方法的源码就会明白了)
Date date1 = new Date(1214314242L);
Date date2 = new Date(1214314242L);
System.out.println(date1.equals(date2)); //run result=>true
System.out.println(date1==date2); //run result=>false
}
}
10 String中的equals源码分析
首先可以知道,这里的equals重写了Object的equals方法
第一步
上面笔误,是父类的引用指向子类的对象
第二步
举例
String wei1 = "dasd";
String wei2 = wei1;
System.out.println(wei1.equals(wei2)); //run result=>true
第三步
11 重写equals方法
手动实现equals的重写
手动实现equals的重写(由于开发中比较常用–我们可以自动生成重写后的方法)
package com.hxut13.java2;
import java.util.Date;
/**
* @author weijiangquan
* @date 2022/4/25 -20:35
*
* 这节课很重要(干货慢慢)
*
* 面试题: ==和equals的区别
*
* 回顾 == 的使用
* ==:运算符
* 1.可以使用在基本数据类型和引用数据类型变量中
* 2.如果比较的是基本的类型变量:比较的两个变量保存的胡数据是否相等 (不一定类型要相同)
* 如果比较的是引用雷类型:比较两个对象的地址值是否相同,即两个引用是否指向同一个对象实体
*
* 二.equals()方法的使用
* 1.是一个方法,而非运算符
* 2.适用与引用数据类型
* 3.Object中equals()的定义
* public boolean equals(Object obj) {
* return (this == obj);
* }
* 说明:Object类中定义的equals()和==的作用是相同的
* 4.像 String,date,File,包装类等都重写了Object类中的equals方法 重写以后,比较的不是两个引用的地址是否相同
* 而是比较两个对象的"实体内容"是否相同
*
* 5.通常情况下,我们自定义的类如果适用equals()的话,也通常是比较两个对象的"实体类内容"是否相同,那么,我们就需要对Object
* 类中的equals()进行重写,
* // 重写的原则:比较两个对象的实体内容(在本类中即:name和age)是否相同
*
*
*
*
*/
public class EqualsTest {
public static void main(String[] args) {
int i = 10;
int j = 10;
double d = 10.0;
System.out.println(i==j); //run result=>true
System.out.println(i==d); //run result=>true 会有基本数据类型的提升
boolean b = true;
// System.out.println(i==b); //run result=>报错 都和布尔类型的完
char c = 10; //这里没有单引号就是10
System.out.println(i==c); //run result=>true
char c1= 'A';
char c2 = 65;
System.out.println(c1==c2);//run result=>true
// 比较引用类型的 Customer是自己定义的是同一类
Customer customer = new Customer("aaa",12);
Customer customer1 = new Customer("aaa",12);
System.out.println(c1==c2); //run result=>false
String str1 = new String("aaa");
String str2 = new String("aaa");
System.out.println(str1==str2);//run result=>false
System.out.println("自定义的对象"+customer.equals(customer1)); //对于equals实际上用到了多态 Object obj
//run result=>false
System.out.println(str1.equals(str2)); //run result=>true
//这里的的equals被重写了和上面的不一样
Date date1 = new Date(1214314242L);
Date date2 = new Date(1214314242L);
System.out.println(date1.equals(date2)); //run result=>true
System.out.println(date1==date2); //run result=>false
/* Object a = "aa";
String bb = "aa";
System.out.println(bb.equals(a));*/ //run result=>true 自己瞎写的
String wei1 = "dasd";
String wei2 = wei1;
System.out.println(wei1.equals(wei2)); //run result=>true
}
}
package com.hxut13.java2;
/**
* @author weijiangquan
* @date 2022/4/25 -20:43
*/
public class Customer {
private String name;
private int age;
public Customer() {
}
public Customer(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
// 重写的原则:比较两个对象的实体内容(在本类中即:name和age)是否相同
@Override
public boolean equals(Object obj){
System.out.println("我是重写之后的this"+this);
if(this == obj){
return true;
}
if(obj instanceof Customer){
Customer customer = (Customer)obj;
//比较两个对象的每一个属性是否都相同
return this.age == customer.age && this.name.equals(customer.name);
}
return false;
}
}
主要的
自动生成
12 equals练习题(p299重要和字符串有关)
package com.hxut13;
import com.sun.org.apache.xpath.internal.operations.Or;
/**
* @author weijiangquan
* @date 2022/4/25 -22:13
*
* equals的练习题
*
*
*/
public class exer4 {
public static void main(String[] args) {
Order order1 =new Order(12,"aa");
Order order2 =new Order(12,"aa");
System.out.println(order1.equals(order2)); //run result=>true
String s1 = "BB";
String s2 = "BB"; //放在了常量池中
System.out.println(s1==s2); //run result=>true 比较特殊的情况
}
}
class Order{
int orderId;
String orderName;
public Order(int orderId,String orderName){
this.orderId = orderId;
this.orderName = orderName;
}
public void setOrderId(int orderId){
this.orderId = orderId;
}
public int getOrderId(){
return orderId;
}
public void setOrderName(String orderName){
this.orderName = orderName;
}
public String getOrderName(){
return orderName;
}
// 重写Object的equals方法 我们自己写的这个不是很完善(有一点的漏洞)
@Override
public boolean equals(Object obj){
if(this == obj){
return true;
}
if(obj instanceof Order){
Order order = (Order)obj; //不点的话 就不能调用Order类中的属性
return this.orderId == order.orderId && this.orderName.equals(order.orderName);
}
return false;
}
}
13 练习题二(p300,后面看)
14 toString()的使用
package com.hxut13.java2;
import java.util.Date;
/**
* @author weijiangquan
* @date 2022/4/26 -0:55
*
* Object类中toString方法的使用,只要没有重写,调用的都是Object对象中的toString
* 1.当我们输出一个对象的引用时,实际上就是调用当前对象的toString()方法
* (这个地方一定要注意,println方法会自己去调用tostring()方法,如果重写了的话就调用你重写的,没有重写的话就调用父类的,没有父类就调用Objectd的,而object中的toString()方法的作用和==没有区别)
*
* 2.Object类中的toString()的定义
* public String toString() {
* return getClass().getName() + "@" + Integer.toHexString(hashCode());
* }
* getClass().getName()得到当前对象的类名 Integer.toHexString(hashCode())通过hashCode之后转换成了十六进制的字符串
*
* 3.像String,Date,File,包装类都重写了Object类中的toString()方法
* 使用调用对象的toString()方法时,返回的"实体内容信息"
*
* 4.自定义类也可以重写toString()方法,当调用此方法时,返回对象的实体内容
*
*
*/
public class ToStringTest {
public static void main(String[] args) {
Customer cust1 = new Customer("tom",22);
System.out.println(cust1); //run result=>com.hxut13.java2.Customer@1b6d3586 -->重写toString之后Customer[name=tom,age=22]
// 底层会调用toString方法 返回给我们一个hasCode的16进制的地址值
System.out.println(cust1.toString()); //run result=>com.hxut13.java2.Customer@1b6d3586 -->重写toString之后Customer[name=tom,age=22]
String str = new String("MM");
System.out.println(str); //run result=>MM
Date date = new Date(8126738426L);//run result=>MM
System.out.println(date.toString());//run result=>Sun Apr 05 09:25:38 CST 1970
}
}
package com.hxut13.java2;
/**
* @author weijiangquan
* @date 2022/4/25 -20:43
*/
public class Customer {
private String name;
private int age;
public Customer() {
}
public Customer(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
// 重写的原则:比较两个对象的实体内容(在本类中即:name和age)是否相同
@Override
public boolean equals(Object obj){
System.out.println("我是重写之后的this"+this);
if(this == obj){
return true;
}
if(obj instanceof Customer){
Customer customer = (Customer)obj;
//比较两个对象的每一个属性是否都相同
return this.age == customer.age && this.name.equals(customer.name);
}
return false;
}
// 手写的 (以后用它自动生成的就行了,没有必要自己写)
public String toString(){
return "Customer[name="+name+","+"age="+age+"]";
}
// 下面是自动生成的
/*
@Override
public String toString() {
return "Customer{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}*/
}
15 Object类的综合练习
package com.hxut13.Exer4;
/**
* @author weijiangquan
* @date 2022/4/26 -1:33
*
* 判断两个对象的颜色是否相同
* 利用equals方法判断半径是否相等,利用toString()方法输出其半径
*/
public class Test {
public static void main(String[] args) {
Circle circle = new Circle(2.3);
Circle circle1 = new Circle(2.3,"white",2.0);
System.out.println("颜色是否相等"+circle.getColor().equals(circle1.getColor()));
System.out.println("半径是否相等"+circle1.equals(circle));//对象比的就是半径(因为对于它进行了重写)
System.out.println(circle); //run result=>Circle{radius=2.3}
System.out.println(circle1); //run result=>Circle{radius=2.3}
}
}
16 单元测试方法的使用
package com.hxut13.java3;
import org.junit.Test;
/**
* @author weijiangquan
* @date 2022/4/26 -1:44
*
* java中jUnit单元测试
* 创建的java类的要求:
* 1.
* ①此类是公共的
* ②此类提供公共无参的构造器
* ③在类中声明单元测试方法
* ④此方法的权限是public 没有返回值 没有形参
* 2.此方法上需要声明注解:@Test,并在单元测试类中导入:import org.junit.Test
* 3.声明好单元测试后就可以在方法体中写代码了
*
* 说明
* 1.如果执行结果没有任何异常:绿色
* 2.如果出现结果异常就会显示红条
*
*
*/
public class JunitTest {
int num =10;
@Test
public void testEquals(){
System.out.println("你好,Test");
}
}
17 包装类的理解
package com.hxut13.java3;
import com.sun.org.apache.xpath.internal.operations.Or;
import org.junit.Test;
/**
* @author weijiangquan
* @date 2022/4/26 -2:08
*
*
* 包装类的使用:
* 1.java提供了八种基本数据类型对应的包装类,使得基本数据类型的变量有类的特征
*
* 2.掌握:基本数据类型,包装类,String三者之间的相互转换
*
*/
public class WrapperTest {
//基本数据类型 --->包装类 调用包装类的构造器
@Test
public void test1(){
int num1 = 10;
Integer int1 = new Integer(num1);
System.out.println(int1); //run result=>10
System.out.println(int1); //run result=>10
System.out.println(int1.toString());//run result=>10
//注意:因为Integer已经重写了toString,所以打印的是内容
Integer int2 = new Integer("123");
System.out.println(int2); //run result=>123
System.out.println(int2.toString());//run result=>123
// Integer int3 = new Integer("121abc"); //这个会报异常
Float f1 =new Float(12.3);
Float f2 = new Float(12.f);
System.out.println(f1);
System.out.println(f2);
Boolean b1 = new Boolean(true);
Boolean b2 = new Boolean("true");
// Boolean b3 = new Boolean("true123"); //run result=>q会报异常
Order order = new Order();
System.out.println(order.isMale); //run result=>false
System.out.println(order.isFemale); //run result=>null
}
}
class Order{
boolean isMale;
Boolean isFemale;
}
18 包装类转换成基本数据类型(基本用不上,用下面19就行了)
// 包装类转换成基本数据类型 调用包装类的 xxxValue()
@Test
public void test2(){
Integer in1 = new Integer(2);
// 由于包装类不能进行加减乘除的运算,但是我们有时候会有这种运算的需求
int i1 = in1.intValue();
System.out.println(i1+1); //run result=>3
Float f1 = new Float(12.3);
float f2 = f1.floatValue();
System.out.println(f2+1); //run result=>13.3
}
19 新特性 自动装箱与自动拆箱
/**
* JDK 5.0 新特性:自动装箱和自动拆箱
*
*/
@Test
public void test3(){
/* int num1 = 10;
//基本数据类型 ---> 包装类的对象
method(num1); //Object obj = num1;*/
// 自动装箱
int num2 = 10;
Integer int1 = num2;
boolean b1 = true;
Boolean b2 = b1; //自动装箱
//自动拆箱 包装类转换成基本类型
System.out.println(int1.toString());
int num3 = int1;
}
20 基本数据类型包装类和String的相互转换
本题目前不是很熟悉,有时间可以再看看
package com.hxut13.exer5;
import java.util.Scanner;
import java.util.Vector;
/**
* @author weijiangquan
* @date 2022/4/26 -8:40
*
* 包装类的练习题
*
*
*
*
*/
public class ScoreTest {
public static void main(String[] args) {
// 1.实例化Scanner,用于从键盘获取学生成绩
Scanner sc = new Scanner(System.in);
//2.创建Vector对象,Vector v = new Vector();相当于原来的数组
Vector v = new Vector();
//3.for(;;)或while(true)方式,给Vector中添加数据 v.addElement(Object obj)
int maxScore = 0;
for(;;){
System.out.println("请输入学生成绩");
int score = sc.nextInt();
// ②当输入负数的时候退出循环
if(score<0){
break;
}
if(score>100){
System.out.println("输入的数据非法,请重新输入");
continue; //这个地方就用的很妙
}
// ①添加操作 v.addElement(Object obj)
/*Integer inScore = new Integer(score);
v.addElement(inScore);*/
v.addElement(score); //自动装箱
// 4.获取学生成绩的最大值
if(maxScore<score){
maxScore = score;
}
}
char level;
for(int i = 0;i<v.size();i++){
Object obj = v.elementAt(i);
//在jdk之前
/*Integer inscore = (Integer)obj;
int score = inscore.intValue();*/
// jdk5.0之后
int score = (int)obj;
if(maxScore -score<=10){
level = 'A';
}else if(maxScore-score<=20){
level = 'B';
}else if(maxScore-score<=30){
level = 'C';
}else {
level = 'D';
}
System.out.println("student-"+"score is"+score+",grade is"+level);
}
}
}
第五天
1 多态的复习(p311-p314)
2 static关键字的使用
我们希望有的数据在内存中只会有一份,不用在每一个对象中都放入这个
3 静态变量与实例得到对比
package com.hxut.java;
/**
* @author weijiangquan
* @date 2022/4/26 -16:19
* static关键字的使用
*
* 1.static:静态的
* 2.static可以用来修饰:属性,方法,代码块,内部类
*
* 3.使用static来修饰属性:静态变量
* 3.1属性是否使用static修饰,又分为静态属性vs非静态属性(实例变量).
* 实例对象:我们创建类的多个对象,每一个对象都独立拥有一套类中的非静态属性.当修改一个对象中的非静态属性时
* 不会导致其它对象中同样的属性值修改
* 静态变量:我们创建了类的多个对象,多个对象共享一个静态变量.当通过某一个对象修改静态变量的时候
* 会导致其它对象调用此静态变量的时候,是修改过的
* 3.2 static修饰属性的其它说明
* ① 静态变量随着类的加载而加载的 可以通过 类.静态变量的方式进行调用
* ② 静态变量的加载早于对象的创建
* ③ 由于类只加载一次,则静态变量在内存中只会存在一份 存在方法区的静态域中
*
* ④ 类变量 实例对象
* 类 yes no
* 对象 yes yes
*
*
* 4.使用static修饰方法
*
*
*
*/
public class StaticTest {
public static void main(String[] args) {
Chinese.nation = "das"; //
Chinese c1 = new Chinese();
c1.name = "姚明";
c1.age = 40;
Chinese c2 = new Chinese();
c2.name = "马龙";
c2.age = 30;
}
}
class Chinese{
String name;
int age;
static String nation;
}
4 类变量和实例变量的内存解析
5 静态方法
package com.hxut.java;
/**
* @author weijiangquan
* @date 2022/4/26 -16:19
* static关键字的使用
*
* 1.static:静态的
* 2.static可以用来修饰:属性,方法,代码块,内部类
*
* 3.使用static来修饰属性:静态变量
* 3.1属性是否使用static修饰,又分为静态属性vs非静态属性(实例变量).
* 实例对象:我们创建类的多个对象,每一个对象都独立拥有一套类中的非静态属性.当修改一个对象中的非静态属性时
* 不会导致其它对象中同样的属性值修改
* 静态变量:我们创建了类的多个对象,多个对象共享一个静态变量.当通过某一个对象修改静态变量的时候
* 会导致其它对象调用此静态变量的时候,是修改过的
* 3.2 static修饰属性的其它说明
* ① 静态变量随着类的加载而加载的 可以通过 类.静态变量的方式进行调用
* ② 静态变量的加载早于对象的创建
* ③ 由于类只加载一次,则静态变量在内存中只会存在一份 存在方法区的静态域中
*
* ④ 类变量 实例对象
* 类 yes no
* 对象 yes yes
* 3.3 静态属性的举例 :System.out Math.PI
*
* 4.使用static修饰方法
* ① 随着类的加载而加载 可以同类.方法()调用
* 静态方法 非静态方法
* 类 yes no
* 对象 yes yes
* 不能通过类掉用非静态的方法
* ②静态方法中只能调用静态方法或静态的属性
* 非静态方法中:既可以调用非静态的方法或属性
*
* 5.static的注意:
* 5.1 在静态的方法内:不能使用this关键字,super关键字
* 5.2 关于静态属性和静态方法的使用,都从生命周期的角度去解释
*
* 6 开发中:如何确定一个属性要声明为static?
* 属性可以被多个对象所共享的,不会随着对象的不同而不同
* 类中的常量也常常声明为static
*
* 开发中:如何确定一个方法是否要声明为static?
* 操作静态属性的方法,通常设置为static
* 工具类中的方法,习惯声明为static的,比如Math,Arrays,Collection
*/
public class StaticTest {
public static void main(String[] args) {
Chinese.nation = "das"; //
System.out.println(Chinese.nation);
Chinese c1 = new Chinese();
c1.name = "姚明";
c1.age = 40;
Chinese c2 = new Chinese();
c2.name = "马龙";
c2.age = 30;
Chinese.show();
}
}
class Chinese{
String name;
int age;
static String nation;
public static void show(){
System.out.println("hello");
}
}
6 自定义ArrayUtil工具类优化
7.static的应用(这个题很经典–值得反复看)
package com.hxut14.java;
/**
* @author weijiangquan
* @date 2022/4/26 -17:56
*/
public class CircleTest{
public static void main(String[] args) {
Circle c1 = new Circle();
Circle c2 = new Circle();
Circle c3 = new Circle(3.1);
System.out.println("c1的id:"+c1.getId()); //run result=>1001
System.out.println("c2的id:"+c2.getId()); //run result=>1002
System.out.println("c3的id:"+c3.getId()); //run result=>1003
System.out.println("创建的圆的个数为"+Circle.getTotal()); //run result=>2
}
}
class Circle {
private double radius;
private int id;
public Circle(){
id = init++; //多个对象共享
total++;
}
public Circle(double radius){
this();
this.radius = radius;
/*id = init++; //多个对象共享
total++;*/
// 或者写成这样
}
private static int total; //记录对象被创造了多少次
private static int init = 1001; //static声明的属性被所有对象共享
public double findArea(){
return 3.14*radius*radius;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
// id和total都只需要get方法就可以了
public int getId(){
return id;
}
public static int getTotal() {
return total;
}
}
8 static练习题 账户信息
一定要记住 在System.out.println();
底层调用了toString()方法
package com.hxut14.exer;
/**
* @author weijiangquan
* @date 2022/4/26 -18:25
*/
public class AccountTest {
public static void main(String[] args) {
Account account = new Account();
Account account1 = new Account("qwerty",2000);
Account.setInterestRate(0.012);
Account.setMinMoney(100);
System.out.println(account); //感觉重写toString方法真的太好了 好像这样只能查看,最后还是要通过get方法获取数据
System.out.println(account1);
System.out.println(Account.getInterestRate());
}
}
package com.hxut14.exer;
/**
* @author weijiangquan
* @date 2022/4/26 -18:18
*/
public class Account {
private int id;
private String pwd = "000000";
private double balance;
private static double interestRate;
private static double minMoney = 1.0;
private static int init = 1001;//用于自动生成id使用
public Account(){
id = init++;
}
public Account(String pwd,double balance){
id = init++;
this.pwd = pwd;
this.balance=balance;
}
public int getId() {
return id;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public double getBalance() {
return balance;
}
public static double getInterestRate() {
return interestRate;
}
public static void setInterestRate(double interestRate) {
Account.interestRate = interestRate;
}
public static double getMinMoney() {
return minMoney;
}
public static void setMinMoney(double minMoney) {
Account.minMoney = minMoney;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", pwd='" + pwd + '\'' +
", balance=" + balance +
'}';
}
}
9.设计模式与单例设计模式
英文: Singleton
简单的说就是套路,通过大量的总结得出来的结论
常见的设计模式有23中,他是独立于语言的
用java比较多
目前没有必要去研究,现在是看不明白的
单例是其中的一种
10 单例的饿汉式实现
懒汉式的实现
package com.hxut14.java2;
import com.sun.org.apache.xpath.internal.operations.Or;
/**
* @author weijiangquan
* @date 2022/4/26 -20:51
*
* 单例模式的懒汉式实现
*/
public class SingletonTest2 {
}
class Order{
//1.私有化类的构造器
private Order(){
}
//2.声明当前的对象,没有初始化
//4.此对象也必须声明为static
private static Order instance = null;
//3.声明public static的返回当前类对象的方法
public static Order getInstance(){
if(instance == null){
instance = new Order();
}
return instance;
}
}
饿汉式的实现
package com.hxut14.java2;
/**
* @author weijiangquan
* @date 2022/4/26 -18:50
*
* 单例设计模式
* 1.就是采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例
*
*
* 2.如何实现?
* 饿汉式 vs 懒汉式
*/
public class SingletonTest1 {
public static void main(String[] args) {
Bank bank1 = Bank.getInstance();
Bank bank2 = Bank.getInstance();
System.out.println(bank1 == bank2);
}
}
//饿汉式
class Bank{
//1.私有化类的构造器
private Bank(){
}
//2.内部创建类的对象
// 要求此对象必须声明为静态的
private static Bank instance = new Bank();
//3.提供公共的静态的方法,返回类的对象
public static Bank getInstance(){
return instance;
}
//
}
总结:
*
* 2.如何实现?
* 饿汉式 vs 懒汉式
*
* 3.区分懒汉式和饿汉式
* 饿汉式: 坏处:对象加载时间过长
* 好处:饿汉式是线程安全的(后面会提到)
* 懒汉式:好处:延长对象的创建
* 目前写法坏处:线程不安全 -->到多线程内容的时候,再修改
11 理解main()方法的语法(p329 了解)
12 类中代码块结构的使用(使用的频率不是很高,但是源码会有)
package com.java3;
/**
* @author weijiangquan
* @date 2022/4/26 -21:38
*
* 类的成员之四:代码块(或初始化块)
* 1.代码块的作用:用来初始化类,对象
* 2.代码块如果有修饰的话,只能用static
* 3.分类:静态代码块 vs 非静态代码块
*
* 静态代码块
* >内部可以有输出语句
* >随着类的加载而执行(不需要点)
* >作用:初始化类的信息
* >如果一个类中定义了多个静态代码块.则按照声明的先后顺序执行
* >静态代码块的执行要优先于非静态代码块的执行
* >静态的代码内只能调用静态的属性,静态的方法,不能调用非静态的结构
*
*
*
* 非静态代码块
* >内部可以有输出语句
* >随着对象的创建而执行
* >每创建一个对象,就执行一次非静态代码块
* >作用:可以在创建对象的时候,对对象的属性等进行初始化
* >如果一个类中定义了多个非静态代码块.则按照声明的先后顺序执行
* >非静态的代码块内可以调用静态的属性,静态的方法,或非静态的属性,非静态的方法
*
* 在开发一般也就定义一个(通常情况下没有必要定义多个)
*
*
*
* 对属性可以赋值的位置
* ① 默认初始化
* ② 显式初始化
* ③ 有了对象以后,可以通过"对象.属性"u或对象.方法的方式进行赋值
* ④ 在代码块中中赋值
*` 执行先后顺序: ① - ②/⑤-③-④
*
*
*
*
*/
public class BlockTest {
public static void main(String[] args) {
// 当使用一个类的时候类就会被加载(属性和方法和会随着类的加载而加载)
String desc = Person.desc; //run result=>hello,static
Person person = new Person(); //run result=>hello block
System.out.println(desc);
}
}
class Person{
String name;
int age;
static String desc = "我是一个人";
public Person(){
}
public Person(String name,int age){
this.name = name;
this.age = age;
}
// 代码块(静态代码块)
static {
System.out.println("hello,static block");
desc = "我是一个爱学习的人";
}
static {
System.out.println("hello,static block1");
}
{
System.out.println("hello block");
age = 1;
}
{
System.out.println("hello block1");
age = 1;
}
//方法
public void eat(){
System.out.println("吃饭");
}
// toString默认的话只会给非静态的方法(属于对象的)
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public static void info(){
System.out.println("我是一个快乐的人");
}
}
开发中代码开的举例(p331关于数据库连接的)
13 代码块的课后练习(p333)
14 final修饰类和方法
package com.java3;
/**
* @author weijiangquan
* @date 2022/4/26 -23:40
*
*
* Final:最终的
*
* 1.final可以用来修饰结构,类,方法,变量
*
* 2.final 用来修饰一个类:不能被其它的类所继承
* 比如String类 System类 StringBuffer类
*
* 3.final修饰一个方法:表明此方法不可以被重写
* 比如:Object中的getClass()获取当前对象所处的类
*
* 4.final 用来修饰变量:此时的变量就称为是一个常量
* 4.1 final修饰属性,可以考虑值的位置有 显式初始化,代码块中初始化,构造器中初始化
* 在方法中是不行的
* 4.2 final修饰的局部变量
* 尤其是使用final修饰形参时,表明此形参是一个常量.当我们调用此方法时
* 给常量形参赋制一个形参.一旦赋值以后,就只能在方法体内使用
* 此形参,但不能进行重新赋值
* static final 用来修饰属性:全局常量
*
*
*
* 对于省份证可以
* public void aaa(final int ia){}
*
*
*
* */
public class FinalTest {
}
第六天
15 抽象类和抽象方法的使用(重要)
本内容的思考为什么需要抽象类呢,它的具体的作用是什么,不要它会有什么影响
现在理解:由于随着子类的越来越多,父类逐渐的失去了作用,不需要通过父类来New对象了.所以就直接让他不能new对象不是更好
package com.hxut.java;
/**
* @author weijiangquan
* @date 2022/4/27 -17:54
*
* Abstract关键字的使用
*
* 1.Abstract可以用来修饰的结构:类,方法
*
* 2.abstract修饰类:抽象类
* > 此类不能实例化
* > 抽象类中一定有构造器,便于子类实例化的时候调用(涉及,子类实例化的全过程)
* > 开发中都会提供抽象类的子类,让子类对象实例化,完成相关的操作
* 3.abstract修饰的方法:抽象方法
* > 抽象方法只有方法的声明,没有方法体
* > 包含抽象方法的类一定是抽象类,反之,抽象类中可以没有抽象方法
* (tips:抽象方法由于没有方法体,如果它不在抽象类中的话,就可以实例化它所在的类,这个时候就可以通过对象调用它,显然相互矛盾)
* > 若子类重写了父类中的所有的抽象方法后,此类方可实例化
* 若子类没有重写父类中的所有抽象方法,则子类也是一个抽象类,需要使用abstract
*
*
*/
public class AbstractTest {
public static void main(String[] args) {
// 一旦Person抽象了,就不可实例化
/*Person p1 =new Person();
p1.eat();*/
}
}
abstract class Creature{
public abstract void breath();
}
abstract class Person extends Creature{
String name;
int age;
public Person(){
}
//抽象方法
public abstract void eat();
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void walk(){
System.out.println("人走路");
}
}
class Student extends Person{
public Student(String name, int age) {
super(name, age);
}
public void eat(){
System.out.println("学生多吃有营养的东西");
}
public void breath(){
System.out.println("通过嘴巴呼吸");
}
}
本节学完比较疑惑的地方:既然抽象方法没有方法体,子类都会对它进行重写的,等于说这个抽象方法没有用到,那么它存在的意义是什么,并且它所在的类是抽象类,那么它就不能造对象,也就不能像多态那样,一个父类类型的引用创建不同的子类对象,可以参考重写equals方法.的过程
希望后面的知识可以接触疑惑
明白了,想多了可以这样写
抽象类A(父类) a = new B(子类)
抽象类A(父类) b = new C(子类)
这样的话一个抽象类里面的抽象方法如果内容没有什么东西可以写的话,就可以将其写成抽象类.这样的话,就更好了.
那不不能不要这个抽象方法吗,子类都自己写一个,这样的话就不能使用多态.
多态的条件中的一条就是方法的重写,只有重写的方法,才可以通过父类的引用进行调用
16 abstract使用的注意点
* abstract使用上的注意点
*1.abstract不能用来修饰:属性,构造器等结构
* Tips(如果构造器定义成抽象的话,那么子类就必须要重写它,显然在前面的继承中提到过构造是只能重载的,不能重写(因为名字不一样),故构造器不能是抽象的)
*2.abstract不能修饰私有方法
* Tips(私有方法显然是不不能重写的,但是继承抽象类的话,就要重写抽象方法,显然相互矛盾)
* abstract 不能修饰静态方法(有点疑惑)
* abstract 不能修饰 final方法
*/
17 例子
没有多态,抽象就没有意义了
package com.hxut.exer;
/**
* @author weijiangquan
* @date 2022/4/27 -18:51
*
* 练习题目
*
*/
public abstract class Employee {
private String name;
private int id;
private double salary;
public Employee(){
super();
}
public Employee(String name, int id, double salary) {
this.name = name;
this.id = id;
this.salary = salary;
}
public abstract void work();
}
package com.hxut.exer;
/**
* @author weijiangquan
* @date 2022/4/27 -18:56
*/
public class CommonEmployee extends Employee{
@Override
public void work() {
System.out.println("在一线干很多的活");
}
}
package com.hxut.exer;
/**
* @author weijiangquan
* @date 2022/4/27 -18:54
*/
public class Manager extends Employee{
private double bonus; //奖金
@Override
public void work() {
System.out.println("管理员工,保证公司赚取更多的钱");
}
public Manager(String name, int id, double salary, double bonus) {
super(name, id, salary);
this.bonus = bonus;
}
}
package com.hxut.exer;
/**
* @author weijiangquan
* @date 2022/4/27 -18:57
*/
public class EmployeeTest {
public static void main(String[] args) {
Employee manager = new Manager("库克",1001,5000,50000);
manager.work();
CommonEmployee commonEmployee = new CommonEmployee();
commonEmployee.work();
}
}
18 创建抽象类的匿名子类对象(之前没有用过的)
目前还不知道类的匿名子类对象有什么作用
比如说,一个Person类是一个抽象的类,相通过它创建一个匿名的子类对象
这里的子类是不存在(匿名的)
可以向下面这样的写
Person p = new Person(){
@Override
public void eat(){
System.out.println("吃东西");
}
@Override
public void breath(){
System.out.println("子类呼吸");
}
}
注意,这个时候创建的不是父类的对象,是临时创建了一个子类的匿名对象,但是在大括号里面必须要重写父类的抽象方法
这个是匿名的子类对象,主要是太懒了,不想创建它的类
下面是更加偷懒的方法(这时候更加简便)
匿名子类的匿名对象
method(new Person(){
@Override
public void eat(){
System.out.println("吃东西");
}
@Override
public void breath(){
System.out.println("子类呼吸");
}
})
像这个只用一次的这样写就更好了
19 模板方法的设计模式与应用场景(没有单例常用)
![在这里插入图片描述](https://img-blog.csdnimg.cn/a3484552b22f4a3ea160290323d5216a.png# pic_center)
开发中有许多的地方需要用到这个设计模式
package com.hxut.java1;
/**
* @author weijiangquan
* @date 2022/4/27 -20:04
*
* 模板设计方法的设计模式
*/
public class TemplateTest {
public static void main(String[] args) {
SubTemplate t = new SubTemplate();
t.spendTime();
}
}
abstract class Template{
//计算某段代码执行所需要花费的时间
public void spendTime(){
long start = System.currentTimeMillis();
this.code();//不确定的部分 易变的部分
long end = System.currentTimeMillis();
System.out.println("花费的时间是"+(end-start));
}
public abstract void code();
}
class SubTemplate extends Template{
@Override
public void code() {
for(int i = 2;i<=Math.sqrt(i);i++){
boolean isFlag = true;
for(int j = 2;j<=Math.sqrt(i);j++){
if(i%j==0){
isFlag = false;
break;
}
}
if(isFlag){
System.out.println(i);
}
}
}
}
20 抽象类的课后练习题(本题的综合性较强,值的多练习)
- 类1
package com.hxut.exer2;
/**
* @author weijiangquan
* @date 2022/4/27 -20:20
*/
public abstract class Employee {
private String name;
private int number;
private MyDate birthday;
public Employee(String name, int number, MyDate birthday) {
this.name = name;
this.number = number;
this.birthday = birthday;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public MyDate getBirthday() {
return birthday;
}
public void setBirthday(MyDate birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "name='" + name + '\'' +
", number=" + number +
", birthday=" + birthday.toDateString();
}
// ", birthday=" + birthday.toDateString() +注意这个地方,自动生成的是birthday
public abstract double earning();
}
package com.hxut.exer2;
/**
* @author weijiangquan
* @date 2022/4/27 -20:28
*
* 按月计算工资
*/
public class SalariedEmployee extends Employee{
private double monthlySalary;//月工资
public double getMonthlySalary() {
return monthlySalary;
}
public void setMonthlySalary(double monthlySalary) {
this.monthlySalary = monthlySalary;
}
public SalariedEmployee(String name, int number, MyDate birthday,double monthlySalary) {
super(name, number, birthday);
this.monthlySalary = monthlySalary;
}
@Override
public double earning() {
return monthlySalary;
}
public String toString(){
return "SalariedEmployee["+super.toString()+"]";
}
}
package com.hxut.exer2;
/**
* @author weijiangquan
* @date 2022/4/27 -20:37
*
*
* 按小时计算工资
*
*
*/
public class HourlyEmployee extends Employee{
private int wage;//每小时的工资
private int hour;//月工作的小时数
public HourlyEmployee(String name, int number, MyDate birthday, int wage, int hour) {
super(name, number, birthday);
this.wage = wage;
this.hour = hour;
}
@Override
public double earning() {
return wage*hour;
}
public String toString(){
return "HourlyEmployee["+super.toString()+"]";
}
}
package com.hxut.exer2;
/**
* @author weijiangquan
* @date 2022/4/27 -20:22
*/
public class MyDate {
private int year;
private int month;
private int day;
public MyDate(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public String toDateString(){
return year+"年"+month+"月"+day+"日";
}
}
package com.hxut.exer2;
import javafx.scene.transform.Scale;
import java.util.Calendar;
import java.util.Scanner;
/**
* @author weijiangquan
* @date 2022/4/27 -20:55
*
* 测试类
*/
public class PayrollSystem {
public static void main(String[] args) {
/*Scanner sc = new Scanner(System.in);
System.out.println("请输入当前的月份");
int month = sc.nextInt();
*/
// 方式二(得到当前的月份)
Calendar calendar = Calendar.getInstance();
int month = calendar.get(Calendar.MONTH);
System.out.println("当前的月份是:"+(month+1)); //run result=>月份是从0开始的
Employee[] emps = new Employee[2]; //创建的是数组(数组不是对象 用父类类型的数组存放子类)
emps[0] = new SalariedEmployee("马森",1002,new MyDate(1333,4,28),1000);
emps[1] = new HourlyEmployee("小陈",2001,new MyDate(1991,5,6),60,240);
for(int i = 0;i<emps.length;i++){
System.out.println(emps[i]);
double salary = emps[i].earning();
System.out.println("月工资为:"+salary);
if((month+1) == emps[i].getBirthday().getMonth()){
System.out.println("生日快乐奖励100元");
}
}
}
}
运行结果
21 接口的理解
还是不能很好的体会接口的作用(我目前还老是在想既然可以实现多个接口,那又和多继承有什么区别呢,无非是换了一个词语罢了)
本节主要是关于JDK1.7的
package com.hxut.day15;
/**
* @author weijiangquan
* @date 2022/4/27 -21:42
*
*
* 接口的使用
* 1.使用interface来定义
* 2.java中,接口和类是两个并列的结构
* 3.如何定义接口,定义接口中的成员
*
* 3.1 JDK7及以前,只能定义常量和抽象方法
* > 全局常量 public static final的,初学的时候可以省略不写
* 如:public static final int MAX_SPEEd = 7900
* 可以写成 int MAX_SPEEd = 7900(默认会帮你加上前缀)
* > 抽象方法 public abstract 的
*
* 3.2 JDK 8 :除了定义全局常量和抽象方法之外,还可以定义静态方法,默认方法(略)
*
* 4.接口不能定义构造器!意味着接口不能实例化
*
* 5.在Java开发中,接口都通过类去实现(implements)的方式来使用
* 如果实现类覆盖了接口中的所有的抽象方法,则此实现类就可以实例化
* 如果实现类没有覆盖接口中所有的抽象方法,则此实现类仍是抽象类
* 6 Java类可以实现多个接口 ---> 弥补了java单继承的局限性
*
* 格式:class AA extends BB implements CC,DD,EE
*
* 7.接口和接口之间可以继承并且可以多继承
*
*
* 8.接口的具体使用,体现多态性
* 9.接口实际上是一种规范
*
*/
public class InterfaceTest {
public static void main(String[] args) {
System.out.println(Flyable.MIN_SPEED);
System.out.println(Flyable.MAX_SPEEd);
Plane plane = new Plane();
plane.fly();
}
}
interface Flyable{
//全局常量
public static final int MAX_SPEEd = 7900; //第一宇宙速度
int MIN_SPEED = 1; //省略了 public static final
//抽象方法
public abstract void fly();
void stop(); //省略了 public abstract
//错误信息: Interface abstract methods cannot have body
// 接口中不能定义构造器
/*public Flyable(){
}*/
}
class Plane implements Flyable{
@Override
public void fly() {
System.out.println("飞机通过引擎起飞");
}
@Override
public void stop() {
System.out.println("驾驶员减速停止");
}
}
// 没有实现全部的抽象方法就要变程抽象类
abstract class Kite implements Flyable{
@Override
public void fly() {
}
}
想一想
经典的面试题:抽象类和接口有什么异同?
都不能实例化
如果将它们放在一个形参中,就一定会体现出多态性
method(Peron a)
如果Person是一个接口或抽象类的化,那么传入的参数一定是子类的对象,体现的是多态性
未完待续
22 案例演示接口是一种规范(应用举例)
package com.hxut.day15;
/**
* @author weijiangquan
* @date 2022/4/27 -22:33\
* 这个例子可以很好的理解接口
*
* 接口的使用
* 1.接口使用上也满足多态性
* 2.接口实际上体现的是一种规范
* 3.在开发中体现面向接口编程
*/
public class USBTest {
public static void main(String[] args) {
Computer com = new Computer();
Flash flash = new Flash();
com.transferData(flash);
}
}
class Computer{
public void transferData(USB usb){
//USB usb = new Flash();
usb.start();
System.out.println("具体的传输数据的细节");
usb.stop();
}
}
interface USB{
//定义了长,宽,最大最小的传输速度等
void start();
void stop();
}
class Flash implements USB {
@Override
public void start() {
System.out.println("U盘开启工作");
}
@Override
public void stop() {
System.out.println("U盘结束工作");
}
}
class Printer implements USB{
@Override
public void start() {
System.out.println("打印机开始工作");
}
@Override
public void stop() {
System.out.println("打印机停止工作");
}
}
运行结果
一定要记住的是体现的是实现类的对象
第七天
1 创建接口匿名实现类的对象
package com.hxut.day15;
/**
* @author weijiangquan
* @date 2022/4/27 -22:33\
* 这个例子可以很好的理解接口
*
* 接口的使用
* 1.接口使用上也满足多态性
* 2.接口实际上体现的是一种规范
*/
public class USBTest {
public static void main(String[] args) {
Computer com = new Computer();
// 根据开发情况进行选择(下面有四种)
// 1.创建接口的非匿名实现类的非匿名对象
Flash flash = new Flash();
com.transferData(flash);
//2.创建了接口的非匿名实现类的匿名对象
com.transferData(new Printer());
//3.创建接口的匿名实现类的非匿名对象
USB phone = new USB(){
@Override
public void start() {
System.out.println("手机开始工作");
}
@Override
public void stop() {
System.out.println("手机结束工作");
}
};
com.transferData(phone);
System.out.println("****************");
// 4.创建了接口的匿名实现类的匿名对象
com.transferData(new USB() {
@Override
public void start() {
System.out.println("mp3开始工作");
}
@Override
public void stop() {
System.out.println("mp3结束工作");
}
});
}
}
class Computer{
public void transferData(USB usb){
//USB usb = new Flash();
usb.start();
System.out.println("具体的传输数据的细节");
usb.stop();
}
}
interface USB{
//定义了长,宽,最大最小的传输速度等
void start();
void stop();
}
class Flash implements USB {
@Override
public void start() {
System.out.println("U盘开启工作");
}
@Override
public void stop() {
System.out.println("U盘结束工作");
}
}
class Printer implements USB{
@Override
public void start() {
System.out.println("打印机开始工作");
}
@Override
public void stop() {
System.out.println("打印机停止工作");
}
}
运行结果
2 接口应用,代理模式(现在代码少,可以不用太深究)
代理模式:Proxy
概述:代理模式是java开发中使用较多的一种设计模式.代理设计就是为其他对象提供一种代理控制对这个对象的访问
到现在,之前会经常听说关于代理模式的这个词,包括前端的vue中和后端.但是却从没有好好的深入的研究它,对于它的概念也一直是模糊的.希望通过本次的学习,可以彻底的弄清楚的原理和作用.
下面是静态代理(以后在了解动态代理类)
静态代理类就是针对某一个接口
package com.hxut.java;
/**
* @author weijiangquan
* @date 2022/4/28 -13:04
*/
public class NetWorkTest {
public static void main(String[] args) {
Server server = new Server();
ProxyServer proxyServer = new ProxyServer(server);
proxyServer.browse();
}
}
interface NetWork{
public void browse();
}
//被代理类
class Server implements NetWork{
@Override
public void browse() {
System.out.println("真实的服务器访问网络");
}
}
//代理类
class ProxyServer implements NetWork{
private NetWork work;
public ProxyServer(NetWork work) {
this.work = work;
}
public void check(){
System.out.println("联网之前的检查工作");
}
@Override
public void browse() {
check();
work.browse();
}
}
后面反射的时候在谈动态代理类
3 接口应用:工场模式
现在了解一下就可以了,以后在深究
简单的说就是创建对象和使用对象进行分离
xxxFactory
看到这个就差不多就是工厂了
工厂模式好强啊
简单工厂
但是却违反了开闭原则
工厂方法可以解决开闭原则
注意重写的方法的类型不大于父类的类型(基本数据类型,引用数据类型)
抽象工厂模式
4 接口课后两道笔试题
package com.hxut.java;
/**
* @author weijiangquan
* @date 2022/4/28 -13:34
*
* 笔试题(开发中不会出现这样的问题,谁没有事会定义同名的变量)
*
*
*/
interface A {
int x = 0;
}
class B{
int x =1;
}
public class C extends B implements A{
public void pX(){
// System.out.println(x); //错误的写法,编译不通过,x不明确
System.out.println(super.x); //调用的父类的x(调用的是B)
System.out.println(A.x); //x是全局常量,直接通过接口.就可以了(调用的是A中的)
}
public static void main(String[] args) {
new C().pX();
}
}
运行结果
5 接口练习:比较对象的大小
package com.hxut.exer;
/**
* @author weijiangquan
* @date 2022/4/28 -13:55
*
* 比较两个对象的大小(在这里实际上是比较两个对象中某一个属性大下)
*
*
*
*/
public class ComparableCircleTest{
public static void main(String[] args) {
ComparableCircle c1 = new ComparableCircle(3.4);
ComparableCircle c2 = new ComparableCircle(4.4);
int compareValue = c1.compareTo(c2);
if(compareValue>0){
System.out.println("c1对象大");
}else if(compareValue<0){
System.out.println("c2对象大");
}else {
System.out.println("一样大");
}
}
}
interface CompareObject {
//若返回值是0,代表相等;若为正数,代表当前对象大,负数代表当前对象小
public int compareTo(Object o);
}
class Circle{
private double radius;
public Circle(double radius) {
this.radius = radius;
}
public Circle() {
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
}
class ComparableCircle extends Circle implements CompareObject{
public ComparableCircle(double radius){
super(radius);
}
@Override
public int compareTo(Object o) {
if(this == o){
return 0;
}
if(o instanceof CompareObject){
ComparableCircle c =(ComparableCircle) o;
//错误的(有漏洞)
// return (int)(this.getRadius() - c.getRadius());
if(this.getRadius()>c.getRadius()){
return 1;
}else if(this.getRadius()<c.getRadius()){
return -1;
}else {
return 0;
}
//当属性设置为Double(注意这里的D是大写,也就是包装类),可以调用包装类的方法
//return this.getRadius().CompareTo(c.getRadius());
}else {
return 0;
// 当学了异常之后就可以用下面的这种方式了
// throw new RuntimeException("传入的数据不合适");
}
}
}
6 java8中接口的新特性
package com.hxut.java8;
/**
* @author weijiangquan
* @date 2022/4/28 -14:22
*
* JDK8中:除了定义全局常量和抽象方法外,还可以定义静态方法,默认方法
*
*
*/
class SubClassTest{
public static void main(String[] args) {
SubClass s = new SubClass();
s.method2();
//s.method1(); //报错)
//知识点一:接口中定义的静态方法,只能通过接口来调用
CompareA.method1();
//知识点二:通过实现类的对象,可以调用接口中默认方法
//如果实现类重写了接口中的默认方法,调用时,仍然调用的时重写以后的方法
s.method2();
//知识点三:如果子类(或实现类)继承父类和实现接口中声明了同名同参数的方法
//那么子类在没有重写此方法的情况下,默认调用的时父类中同名同参数的方法 -->类优先原则(仅针对的时方法)
//知识点4:如果实现类实现了多个接口,而这多个接口中定义了同名同参数的默认方法,
//那么在实现类没有重写的情况下,报错---->接口冲突
//就必须要我们在此实现类中重写此方法
// 知识点五:如何在子类(或实现类中嗲用父接口中的被重写的方法) 如 CompareA.super.method3() 其中CompareA是父接口
s.method3();
}
}
public interface CompareA {
//静态方法
public static void method1(){
System.out.println("CompareA:北京");
}
// 默认方法
public default void method2(){
System.out.println("CompareA:上海");
}
// 默认方法
default void method3(){
System.out.println("CompareA:上海");
}
}
class SubClass extends SuperClass implements CompareA,CompareB{
public void method2(){
System.out.println("SuperClass:北京");
}
}
class SuperClass{
public void method3(){
System.out.println("SuperClass:北京");
}
}
interface CompareB{
default void method() {
System.out.println("CompareB:o上海");
}
}
7 java8新特性的应用
package com.hxut;
/**
* @author weijiangquan
* @date 2022/4/28 -15:32
*/
interface Filial{
//孝顺的
default void help(){
System.out.println("老妈,我来救你了");
}
}
interface Spoony{
//痴情的
default void help(){
System.out.println("救老婆");
}
}
class Man implements Filial,Spoony{
@Override
public void help() {
System.out.println("我不知道救谁");
}
}
在上面的例子中Man这个类必须要重写两个接口共有的方法,不然就会报错
package com.hxut;
/**
* @author weijiangquan
* @date 2022/4/28 -15:32
*/
interface Filial{
//孝顺的
default void help(){
System.out.println("老妈,我来救你了");
}
}
interface Spoony{
//痴情的
default void help(){
System.out.println("救老婆");
}
}
class Father{
public void help(){
System.out.println("救我媳妇");
}
}
class Man extends Father implements Filial,Spoony{
@Override
public void help() {
super.help();
Filial.super.help(); //救它妈
Spoony.super.help(); //救它媳妇
}
}
8 内部类的使用(不是重要)
package com.hxut.java3;
/**
* @author weijiangquan
* @date 2022/4/28 -15:42
*
* 类的内部成员之五:内部类
* 1.java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B就是外部内
*
* 2.内部类的分类:成员内部类(静态,非静态) vs 局部内部类(方法内,代码块内,构造器内)
*
*
*
*/
public class InnerClassTest {
}
class Person{
// 静态成员内部类
static class Dog{
}
//非静态成员内部类
class Bird{
}
public void method(){
//局部内部类
class AA{
}
}
{
//局部内部类
class BB{
}
}
public Person(){
//局部内部类
class CC{
}
}
}
9 成员内部类的特点
package com.hxut.java3;
/**
* @author weijiangquan
* @date 2022/4/28 -15:42
*
* 类的内部成员之五:内部类
* 1.java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B就是外部内
*
* 2.内部类的分类:成员内部类(静态,非静态) vs 局部内部类(方法内,代码块内,构造器内)
*
* 3.成员内部类:
* 一方面,作为外部类的成员
* >调用外部的结构
* > 可以被static修饰(注意外部类不能被static修饰)
* > 可以被四中不同的权限修饰
*
* 另方方面,作为一个类:
* > 类内可以定义属性方法,构造器等
* > 可以被final修饰,表示此类不能被继承,反之救可以被继承
* > 可以被abstract修饰(不能被实例化了)
*
*/
public class InnerClassTest {
}
class Person{
String name;
int age;
public void eat(){
System.out.println("人吃饭");
}
// 静态成员内部类
static class Dog{
String name;
int age;
public void show(){
System.out.println("我是一条狗");
}
}
//非静态成员内部类
class Bird{
String name;
public Bird(){
}
public void Sing(){
System.out.println("唱歌");
eat(); //简写
// Person.this.eat(); //调用外部类的非静态属性
}
}
public void method(){
//局部内部类
class AA{
}
}
{
//局部内部类
class BB{
}
}
public Person(){
//局部内部类
class CC{
}
}
}
10 如何实例化成员内部类
其它的代码都在上面
11 成员的内部类中调用外部类的结构
package com.hxut.java3;
/**
* @author weijiangquan
* @date 2022/4/28 -15:42
*
* 类的内部成员之五:内部类
* 1.java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B就是外部内
*
* 2.内部类的分类:成员内部类(静态,非静态) vs 局部内部类(方法内,代码块内,构造器内)
*
* 3.成员内部类:
* 一方面,作为外部类的成员
* >调用外部的结构
* > 可以被static修饰(注意外部类不能被static修饰)
* > 可以被四中不同的权限修饰
*
* 另方方面,作为一个类:
* > 类内可以定义属性方法,构造器等
* > 可以被final修饰,表示此类不能被继承,反之救可以被继承
* > 可以被abstract修饰(不能被实例化了)
*
* 4.关注如下3个问题
* 4.1 如何实用化成员内部类的对象
* 4.2 如何在成员内部类中区分调用外部类的结构
* 4.3 开发中局部内部类的使用
*/
public class InnerClassTest {
public static void main(String[] args) {
//创建Dog实例(静态的成员内部类):
Person.Dog dog = new Person.Dog();
dog.show();
// 创建Bird实例(非静态的成员内部类)
// Person.Bird bird = new Person.Bird(); //错误的写法
Person p = new Person();
Person.Bird bird = p.new Bird();
bird.sing();
System.out.println("********************");
bird.display("我是形参的");
}
}
class Person{
String name = "我是Person的成员变量";
int age;
public void eat(){
System.out.println("人吃饭");
}
// 静态成员内部类
static class Dog{
String name;
int age;
public void show(){
System.out.println("我是一条狗");
}
}
//非静态成员内部类
class Bird{
String name = "我是内部类的成员变量";
public Bird(){
}
public void sing(){
System.out.println("唱歌");
eat(); //简写
// Person.this.eat(); //调用外部类的非静态属性
}
public void display(String name){
System.out.println(name);
System.out.println(this.name);
System.out.println(Person.this.name);
}
}
public void method(){
//局部内部类
class AA{
}
}
{
//局部内部类
class BB{
}
}
public Person(){
//局部内部类
class CC{
}
}
}
运行结果
本节主要关注的代码
12 局部内部类的使用
package com.hxut.java3;
/**
* @author weijiangquan
* @date 2022/4/28 -16:18
*/
public class InnerClassTest1 {
//开发中少见
public void method(){
//局部内部类
class AA{
}
}
//开发中常见(这个比较常用)
//返回一个实现了Comparable接口的类对象
public Comparable getComparable(){
//创建一个实现了Comparable接口的类:局部内部类
// 方法一
/*class MyComparable implements Comparable{
@Override
public int compareTo(Object o) {
return 0;
}
}
return new MyComparable();*/
// 方式二
return new Comparable() {
@Override
public int compareTo(Object o) {
return 0;
}
};
}
}
13 抽象类和接口有哪些共同点和区别?
相同点:不能实例化,都可以被继承,接口可以被多继承
不同点:抽象类:有构造器.接口:不能声明构造器
14 p366-p370复习
异常
1 异常的概述
package com.hxut.day16.java1;
/**
* @author weijiangquan
* @date 2022/4/28 -17:51
*
*
*
* Error:java虚拟机都无法解决的严重问题.如:JVM系统内部错误,资源耗尽等严重情况
* StackOverflowError
*/
public class ErrorTest{
public static void main(String[] args) {
//1.栈溢出:Exception in thread "main" java.lang.StackOverflowError
// main(args);
//2.堆溢出:Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
Integer[] arr = new Integer[1024*1024*1024];
}
}
Exception是本章研究的重点
2 异常处理,异常的分类
package com.hxut.day16.java1;
import org.junit.Test;
import java.io.File;
import java.io.FileInputStream;
import java.util.Date;
/**
* @author weijiangquan
* @date 2022/4/28 -18:06
*
*
* 一.异常的体系结构
* java.lang.Throwable
* |----java.lang.Error:一般不编写针对性的代码进行处理
* |----java.lang.Exception:可以进行异常的处理(常见的如下)
* |---编译时异常(checked)
* |----IOException
* |---ClassNotFoundException
* |---运行时异常(unchecked)
* |--NullPointerException
* |--ArrayIndexOutOfBoundsException
* |--NumberFormatException
* |--ArithmeticException
*
*/
public class ExceptionTest {
//***************************************
// 以下是编译时的异常
public void test7(){
/*File file = new File("hello.txt");
FileInputStream fis = new FileInputStream(file);
int data = fis.read();
while (data!=-1){
System.out.println((char)data);
data = fis.read();
}
fis.close();*/
}
//******************下面是运行时的异常***********************
// NullPointerException
@Test
public void test1(){
/*int[] arr = null;
System.out.println(arr[3]);*/
}
// ArrayIndexOutOfBoundsException
@Test
public void test2(){
int[] arr = new int[10];
System.out.println(arr[10]);
}
// ClassNotFoundException
@Test
public void test3(){
Object obj = new Date();
String str = (String)obj;
}
// NumberFormatException
@Test
public void test4(){
// 这个可以转
/*String str = "123";
int num = Integer.parseInt(str);*/
// 这个不可以转
String str = "abc";
int num = Integer.parseInt(str);
}
// ArithmeticException
@Test
public void test6(){
int a = 10;
int b = 0;
System.out.println(a/b);
}
}
3 异常处理 异常的处理方式概述(重点)
package com.hxut.day16.java1;
import org.junit.Test;
/**
* @author weijiangquan
* @date 2022/4/28 -18:40
*
* 异常处理:抓抛模型
* 过程一:"抛",程序在执行的过程中,一旦出现异常,就会在异常代码出生成一个对应异常类对象
* 并将此对象抛出
* 一旦抛出异常,其后的代码将不再执行
*
* 过程二:"抓",可以理解为异常的处理模式: ①try-catch-finally ②throws
*
*
* 二.try-catch-finally的使用
*
* try{
* //可能出现异常的代码
* }catch(异常类型1,变量名1){
* //处理异常的方式
* }catch(异常类型1,变量名1){
* //处理异常的方式
* }finally{
* //一定会执行的代码
* }
*
* 快捷键 ctrl+alt+t 选择try-catch
*
* 说明:
* 1.finally是可选的
* 2.使用try将可能出现异常代码块包装起来,在执行的过程中,一旦出现异常,就会出现一个异常类的对象,根据此对象的类型
* ,去catch中进行匹配
* 3.一旦try中的异常对象匹配到某一个catch时,就进入catch中进行异常的处理,一旦处理完成,就跳出try-catch语句
* (没有写finally的情况),继续执行其后的代码
* 4.catch中的异常类型如果没有子父类的关系,则谁声明在上,没有关系
* 一旦有子父类的关系,子类的必须写在父类的上面
*
* 5.常用的异常处理的方式:① String getMessage() ② printStackTrace()(常用)
*
* 6.在try结构中声明的变量,在出了try结构以后,就不能再调用了
* 7.try-catch可以嵌套
*
*
* 体会一:使用try-catch-finally处理编译时的异常,是让程序编译时不再报错,但是运行时仍然可能报错,相当于使用try-catch-finally将一个编译可能出现的异常延迟到运行时出现
* 体会二:开发中由于运行时异常比较常见,所以我们通常就不针对运行时异常编写try-catch-finally了.针对编译时异常,我们一定要考虑异常的处理.
*
*/
public class ExceptionTest1 {
@Test
public void test1(){
String str = "123";
str = "abc";
try {
int num = Integer.parseInt(str);
System.out.println("hello-------1");
} catch (NumberFormatException e) {
// System.out.println("出现数值转换异常了不要着急.....");
// 自带的两种方式
// 方式一:简陋版
// System.out.println(e.getMessage());
//方式二:详细版
e.printStackTrace();
} catch (Exception e){
System.out.println("出现异常了不要召集");
}
System.out.println("hello---------2");
}
}
4 finally的使用
package com.hxut.day16.java1;
import org.junit.Test;
/**
* @author weijiangquan
* @date 2022/4/28 -19:44
*
* try-catch---finally中的finally的使用
*
* 1.finally是可选的
* 2.finally中声明的一定是会被执行的代码,即使catch中又出现异常了,try中有return语句,catch中有return语句
* 3.什么时候会将东西写再finally中
* 像数据库的连接,输入输出流,网络编程Socket等资源,JVM是不能自动回收的,我们需要自己手动的进行资源的释放
* ,此时的资源的释放,就需要声明在finally中
*
*
*
*
* */
public class FinallyTest{
@Test
public void test1(){
try {
int a = 10;
int b = 0;
System.out.println(a/b);
} catch (ArithmeticException e) {
e.printStackTrace();
}catch (Exception e){
e.printStackTrace();
}finally {
System.out.println("我好帅啊");
}
}
}
使用finally
理由
5 异常处理-处理异常:thorws方式
package com.hxut.day16.java1;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* @author weijiangquan
* @date 2022/4/28 -20:13
*
*
*
* 异常处理的方式二:throws + 异常类型 写在方法的声明处.指明此方法执行时,可能出现的异常类型
* 一旦当方法体执行时,出现异常,仍然会在异常代码处生成一个异常类的对象.此对象满足throws后面的异常类型时,就会被抛出
*
* 异常后续的代码就不再执行了
*
* 2.体会:try-catch-finally:真的将异常处理掉了
* throws的方式只是将异常抛给了方法的调用者,并没有真正的将异常处理掉
*
*/
public class ExceptionTest2 {
public static void main(String[] args) {
try {
method1();
}catch (IOException e){
e.printStackTrace();
}
}
public static void method2()throws IOException{
method1();
}
public static void method1() throws FileNotFoundException,IOException{
File file = new File("hello");
FileInputStream fis = new FileInputStream(file);
int data = fis.read();
while (data != -1){
System.out.println((char)data);
data = fis.read();
}
fis.close();
}
}
面向高级部分
第八天
1 重写方法异常抛出的规则
package com.hxut.day17.java1;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* @author weijiangquan
* @date 2022/4/29 -15:51
*
* 方法重写的规则之一
* 子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型(通过下面的例子可以确定)
*/
public class OverrideTest {
public static void main(String[] args) {
OverrideTest test = new OverrideTest();
test.display(new SubClass());
}
public void display(SuperClass s){
try {
s.method();
}catch (IOException e){
e.printStackTrace();
}
}
}
class SuperClass{
public void method() throws IOException{
}
}
class SubClass extends SuperClass{
public void method() throws FileNotFoundException {
}
}
2 开发中选择哪种异常处理方式
package com.hxut.day16.java1;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* @author weijiangquan
* @date 2022/4/28 -20:13
*
*
*
* 异常处理的方式二:throws + 异常类型 写在方法的声明处.指明此方法执行时,可能出现的异常类型
* 一旦当方法体执行时,出现异常,仍然会在异常代码处生成一个异常类的对象.此对象满足throws后面的异常类型时,就会被抛出
*
* 异常后续的代码就不再执行了
*
* 2.体会:try-catch-finally:真的将异常处理掉了
* throws的方式只是将异常抛给了方法的调用者,并没有真正的将异常处理掉
*
*
* 3.开发中如何选择使用try-catch-finally 还是使用throws?
* 3.1 如果父类中被重写的方法没有throws方式处理异常,则子类重写的方法也不能使用throws,意味着,子类
* 中重写的方法有异常,必须使用try0=-catch-finally方式处理.
* 3.2 执行的方法中另外的又调用了另外的几个方法,这几个方法是递进的关系执行的.我们建议这几个方法使用throws
* 的方式进行处理.而执行的方法a可以考虑使用try-catch-finally方式进行处理.
*
*
*
*
*/
public class ExceptionTest2 {
public static void main(String[] args) {
try {
method1();
}catch (IOException e){
e.printStackTrace();
}
}
public static void method2()throws IOException{
method1();
}
public static void method1() throws FileNotFoundException,IOException{
File file = new File("hello");
FileInputStream fis = new FileInputStream(file);
int data = fis.read();
while (data != -1){
System.out.println((char)data);
data = fis.read();
}
fis.close();
}
}
3 手动抛出异常
关于异常
- 系统自动生成的异常对象
- 手动的生成一个异常对象,并抛出(throw)
package com.hxut.day17.java2;
/**
* @author weijiangquan
* @date 2022/4/29 -16:14
*
*
*
*/
public class StudentTest{
public static void main(String[] args) throws Exception {
try {
Student student =new Student();
student.regist(-1001);
System.out.println(student);
} catch (Exception e) {
System.out.println(e.getMessage());
}
// 输入的是非法的时候
}
}
class Student {
int id;
public void regist(int id) throws Exception {
if(id>0){
this.id = id;
}else {
// throw new RuntimeException("输入的数据非法"); 运行时的异常
throw new Exception("您输入的数据非法");
}
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
'}';
}
}
4 如何自定义异常
package com.hxut.day17.java2;
/**
* @author weijiangquan
* @date 2022/4/29 -16:30
*
* 1.如何自定义异常:RuntimeException,Exception
* 2.提供全局常量serialVersionUID
* 3.T提供重载的构造器
*
*/
public class MyException extends Exception{
static final long serialVersionUID = -7034827190745766939L; //抄源码的
public MyException() {
}
public MyException(String message) {
super(message);
}
}
5 异常的练习题(本题综合了本章的全部内容)
package com.hxut.day17.exer;
/**
* @author weijiangquan
* @date 2022/4/29 -16:52
* 如果定义的是非运行时的异常,我们就要将其进行抛出
*
* 像运行时的异常一般情况下是可以不用处理的
*
*/
public class EcmDef{
public static void main(String[] args){
try {
int i = Integer.parseInt(args[0]);
int j = Integer.parseInt(args[1]);
int result = ecm(i, j);
System.out.println(result);
} catch (NumberFormatException e) {
System.out.println("数据类型不一致");
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("缺少命令行参数");
}catch (ArithmeticException e){
System.out.println("除0");
}catch (EcDef e){
System.out.println(e.getMessage());
}
}
public static int ecm(int i,int j) throws EcDef {
if(i<0||j<0){
throw new EcDef("分子或分母为负数了");
}
return i/j;
}
}
// 自定以的异常
class EcDef extends Exception{
static final long serialVersionUID = -3387516193124229948L; //把数字稍微改一下就行了
public EcDef() {
}
public EcDef(String message) {
super(message);
}
}
6 异常总结的