面向对象高级编程 全课程

文章目录

  • 序章 课程内容总览
  • 第一章 面向对象编程基础
    • 引入
    • 类与对象
    • 封装
      • 程序结构
      • 类结构
      • 类结构与封装
      • 变量与数据类型
      • 变量访问与生存期
      • 为什么class中变量用private?方法用public?——封装性的强化
        • 补充知识:Java内存管理
      • 类的实例化
      • 函数
      • 函数的参数传递
      • 函数重载
      • 字符串
      • 标准输入输出
        • 标准输入流
          • next() 与 nextLine()的区别
        • 输出流
        • 文件输入输出
      • 控制流
      • 数组
        • for-each 循环
    • 继承关系
      • 继承与复用
      • 子类实例化
      • 接口与多态
      • 泛型与类型安全
        • 泛型的引入
        • 泛型类与接口
        • 泛型类的使用
        • 泛型的命名规范
        • 泛型方法与构造方法
        • 泛型的继承与子类型
        • 泛型参数界限与通配符
    • 对象关系
      • 关联
      • 组合
      • 聚合
      • 依赖
    • 其他特征
      • 原始类型的装箱和拆箱
        • 什么是装箱?什么是拆箱?
        • 装箱和拆箱是如何实现的
          • 为什么使用ArrayList< Integer >?
          • final类是什么?
      • 枚举类
      • 内部类与匿名类(迭代器)
      • 反射与动态编程
  • 第二章 面向对象设计思想——设计原则与设计模式
    • 设计原则
      • 其他原则
        • 关注点分离![在这里插入图片描述](https://img-blog.csdnimg.cn/36f3f2dbca9e458395b6a250b14c918e.png)
        • 抽象原则
      • SOLID
        • 职责分配原则
    • 创造者模式
      • 单例模式
      • 原型模式
        • 实验2 设计小游戏让人物跑起来
    • 结构型模式
      • 适配器模式
        • 实验3 动图字幕编辑器
      • 代理模式(动态代理)
        • 实验6 带日志功能的计算器
    • 行为型模式
      • 状态模式
        • 实验4 角色状态控制
      • 职责链模式(迭代器)
        • 实验5 基于职责链的计算器
        • 实验5 支持迭代访问的整型列表
      • 观察者模式
        • 实验7 环境监控程序
  • 第三章 Java核心技术
        • 实验8 多线程与网络编程

序章 课程内容总览

面向对象高级编程 全课程_第1张图片

第一章 面向对象编程基础

引入

面向对象的历史。

类与对象

类(class)是对象(object)的设计图纸,定义了对象的数据结构和操作。

封装

程序结构

面向对象高级编程 全课程_第2张图片

类结构

面向对象高级编程 全课程_第3张图片

类结构与封装

面向对象高级编程 全课程_第4张图片

变量与数据类型

面向对象高级编程 全课程_第5张图片

变量访问与生存期

面向对象高级编程 全课程_第6张图片
局部变量:method()里的 int n = 0;
对象成员变量:double v1 = 100;
类成员变量:static int V = 100;
面向对象高级编程 全课程_第7张图片

为什么class中变量用private?方法用public?——封装性的强化

public class circle()
{
	private double radius;
	
	public circle(double radius)
	{
		this.setradius(radius);
	}
	public double getradius()
	{
		return radius;
	}
	public void setradius()
	{
		this.radius = radius;
	}
}
补充知识:Java内存管理

面向对象高级编程 全课程_第8张图片

类的实例化

面向对象高级编程 全课程_第9张图片

函数

面向对象高级编程 全课程_第10张图片

函数的参数传递

值传递。
值的两种类型:原始类型和引用类型。
面向对象高级编程 全课程_第11张图片

函数重载

面向对象高级编程 全课程_第12张图片

字符串

面向对象高级编程 全课程_第13张图片

标准输入输出

面向对象高级编程 全课程_第14张图片

public class Test{
public static void main(String[] args)
{
	Scanner input = new Scanner(System.in);
	System.out.print("输入信息:")String s = input.next();
	System.out.println("打印信息:"+ s);
}
标准输入流

System.in为标准输入流,需要联合Scanner类一起使用。
Scanner sc = new Scanner(System.in);
Scanner类提供了多种读取的方式:nextInt读取下一个整数,nextLine读取下一行等。
注意:因为此种输入方式是可见的,所以Scanner类不适用于从控制台读取密码。Java6特别引入了Console类来实现这个目的。

import java.util.Scanner; // 需要导入 util 包

Scanner input = new Scanner(System.in);
String str1 = input.next();
String str2 = input.nextLine(); // 获取字符串
int number1 = input.nextInt(); // 获取整数
float number2 = input.nextFloat(); // 获取浮点数据

//循环输入
while (input.hasNextInt()) {
	int tmp = input.nextInt();
}
System.out.println(tmp); // 与println效果相同
input.close(); // 掉用完成关闭方法


next() 与 nextLine()的区别

next()
一定要读取到有效字符后才可以结束输入。
对输入有效字符之前遇到的空白,next()方法会自动将其去掉。
只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。
next()不能得到带有空格的字符串。
nextLine()
以Enter为结束符,也就是说nextLine()方法返回的是输入回车之前的所有字符。
可以获取到空白。

输出流

1、标准输出流
最常用的就是标准输出流
System.out.println();

2、格式化输出
除此之外,还可以格式化输出。Java5沿用了C语言函数库中的printf方法。
System.out.printf("%8.2f",x);

文件输入输出

想要读取一个文件,需要构造一个Scanner对象
Scanner in = new Scanner(Path.of("myfile.txt"),StandardCharsets.UTF_8);
如果想写入一个文件,则需要构造一个PrintWriter对象
PrintWriter out = new PrintWriter("myfile.txt",StandardCharsets.UTF_8);
对于这种相对文件名的方式指定的,其实际位置位于Java虚拟机启动目录的位置。
需要注意的是,访问不存在的文件或写入的文件名不合规则会抛出异常。

控制流

面向对象高级编程 全课程_第15张图片

数组

面向对象高级编程 全课程_第16张图片

for-each 循环

for-each循环是Java相比C语言中的for循环拓展而来的一种新的遍历数组的循环方式。for-each循环通过对数组内元素类型相同的变量进行遍历,直接数组内从下标为0的位置至最后一个位置的元素的元素值。

for-each循环基本语句

for ( 变量类型  变量名 : 数组名 ) {
    
    需要执行的循环语句;
 
}

示例

int [] a = new int [10];
 
//for循环遍历
 
for ( int i=0 ; i<10 ; i++ )
    a[i];
 
//for-each循环遍历
 
for ( int k : a);

实例

import java.util.Scanner;
 
public class Main {
 
	public static void main(String[] args) {
		
		int [] data = {56, 75, 68, 45, 24, 245, 2, 5, 22, 27, 5};
		int x = 0;
		Scanner in = new Scanner ( System.in );
		x = in.nextInt();
		
		boolean found = false;
		for ( int k : data ) {
			if ( k==x ) {
				found = true;
				break;
			}
		}
		
		if ( found )	
			System.out.println("找到了");
		else 	
			System.out.println("没找到");
		
		in.close();
	}
 
}

继承关系

面向对象高级编程 全课程_第17张图片

继承与复用

面向对象高级编程 全课程_第18张图片
Java只支持单继承。
B继承A后,可以调用A的方法。

面向对象高级编程 全课程_第19张图片
不能,找不到这个按键了(没有高级功能)。

子类实例化

面向对象高级编程 全课程_第20张图片

接口与多态

面向对象高级编程 全课程_第21张图片

使用interface的方法,抽象类中的抽象函数实质上也是属于接口范畴。
面向对象高级编程 全课程_第22张图片

泛型与类型安全

泛型编程是JAVA 5加入的特征,实现代码中类型参数化的功能。
面向对象高级编程 全课程_第23张图片

泛型的引入

Java泛型的应用可以提高代码的复用性,同时泛型提供了类型检查,减少了数据的类型转换,同时保证了类型的安全。下面来看一下,泛型如何保证了类型的安全:

  List list = new ArrayList();
 
    list.add("abc");
 
    list.add(new Integer(1)); //可以通过编译
 
    for (Object object : list) {
 
           System.out.println((String)object);//抛出ClassCastException异常
 
    }

上面的代码会在运行时抛出ClassCastException,因为它尝试将一个Integer转换为String。接着,来看一下从java5开始,Collection的用法:

 List<String> list = new ArrayList<>();
 
 list.add("abc");
 
 //list.add(new Integer(1)); //编译错误
 
 for (String string : list) {
 
      System.out.println(string);//无需任何强制类型转换
 
 }

注意到,List的创建增加了类型参数String,因此只能向list添加String类型对象,添加其他对象会抛出编译异常;同样可以注意到,foreach循环不需要再添加任何强制类型转换,也就移除了运行时的ClassCastException异常。

泛型类与接口

既然是学泛型,自然就要知道如何去使用泛型定义自己的类和接口。同时为了加深理解泛型的作用,我们先定义一个不适用泛型的类:

public class Gen {
 
     private Object obj;
 
     public Object getObj() {
 
        return obj;
 
     }
 
     public void setObj(Object obj) {
 
        this.obj = obj;
 
     }
 
     public static void main(String[] args) {
 
        Gen gen = new Gen();
 
        gen.setObj("abc");
 
        String str = (String) gen.getObj();//类型转换,可能会引起运行时ClassCastException
 
       }
 
}

原始类的定义,容易引发ClassCastException,因为在使用的时候我们无法知道具体的类型到底是什么。现在来看一下泛型类来重新定义Gen — 使用<>指定泛型参数,如下:

public class Gen<T> {
 
T obj;
 
public T getObj() {
 
return obj;
 
}
 
public void setObj(T obj) {
 
this.obj = obj;
 
}
 
public static void main(String[] args) {
 
Gen<String> gen = new Gen<>();
 
gen.setObj("abc");
 
// gen.setObj(10); //无法通过编译
 
String str = gen.getObj(); //无需类型转换
 
//-----------------------------
 
Gen gen2 = new Gen();//raw type原始类型
 
gen2.setObj("abc");
 
gen2.setObj(10); //可以通过编译,自动装箱将10转化为Integer对象
 
Integer num = (Integer) gen2.getObj();//使用了强制类型转换
 
}
 
}

main()方法里是使用泛型类型Gen,便不再需要强制类型转换,也就移除了运行时的ClassCastException。同时为了区别,在此也定义了一个没有使用泛型类型的gen2,这时,编译器会弹出一个警告“Gen is a raw type,References to generic type Gen should be parameterized”。当我们不提供泛型类型时,会默认使用Object会代替,也是因此这样,gen2可以设置String和Integer类型,不过,我们应尽量去避免这种这种情况的出现,如此,便又需要用到强制类型转换,也伴随着运行时的ClassCastException异常。

可以使用@SuppressWarnings(“rawtypes”)来忽略编译器弹出警告。

接口的泛型应用和类的泛型应用非常类似:

public interface List <E> {
 
 void add(E x);
 
 Iterator<E> iterator();
 
}
 
 
 
public interface Iterator<E> {
 
 E next();
 
 boolean hasNext();
 
}

另外,在定义泛型类和泛型接口的时候,我们也可以定义多个泛型化参数。例如Java中的Map

泛型类的使用

在使用泛型类的时候,我们就需要将泛型参数具体化,例如:

public static void main(String[] args) {
 
ArrayList<String> list = new ArrayList<>();
 
list.add("ABC");
 
list.add(123);//报错!由于泛型已经具体化成String类型,就不能使用整数类型了
 
}

需要注意的是,当我们将泛型参数具体化成String类型之后,原本ArrayList中的add(E e)方法的参数类型就会变成String类型,这时候在调用add()方法的时候,就只能传入String类型的参数了。

另外,在Java中明确的规定了泛型参数在具体化的时候只能使用引用类型,所以是有的泛型参数必须使用Object类型及其子类类型,如果使用基本类型,就会出错:

//这里不能使用基本类型来具体化泛型参数
 
ArrayList<int> list = new ArrayList<>();

泛型类的继承和泛型接口的实现

我们在实现泛型接口的时候,也必须要定义泛型类去实现泛型接口。例如:

public class ArrayList<E> implements List<E>{
 
 
 
}
泛型的命名规范

为了更好地去理解泛型,我们也需要去理解java泛型的命名规范。各种常用泛型参数的意义如下:

E — Element,常用在java Collection里,如:List,Iterator,Set

K,V — Key,Value,代表Map的键值对

N — Number,数字

T — Type,类型,如String,Integer等等

S,U,V etc. - 2nd, 3rd, 4th 类型,和T的用法一样。
泛型方法与构造方法

有些时候,我们可能并不希望将整个类都泛型化。这个时候我们就可以只在某个方法上定义泛型,构造方法也是一样。例如:

public class GenMethod {
 
    public static <T> void fromArrayToCollection(T[] a,Collection<T> c){
 
        for (T t : a) {
 
              c.add(t);
 
        }
 
    }
 
    public static void main(String[] args) {
 
        Object[] oa = new Object[100];
 
        Collection<Object> co = new ArrayList<>();
 
        GenMethod.<Object>fromArrayToCollection(oa, co);
 
   }
 
}

定义方法所用的泛型参数需要在修饰符之后添加,如上面的,public static ,如果有多个泛型参数,可如此定义或者

泛型的继承与子类型

如果两个类之间有继承被被继承的关系,那么我们就可以将一个类的对象赋值类另外一个类的对象,比如:

String str = new String();
 
Object obj = new Object();
 
obj = str;

这种关系同样适用于泛型。比如我们将泛型参数设置为Number,那么在随后的调用中,就只需要传入一个Number类型或者是Number的子类类型的对象就行了,比如Integer,Float,Double都可以:

ArrayList<Number> list = new ArrayList<>();
 
list.add(new Integer(1));
 
list.add(new Float(1.0));
 
list.add(new Double(1.0));

但是有一种情况是我们需要特别注意的,比如我们定义一个如下的方法:

public void someMethod(ArrayList<Number> n) {
 
}

这个方法能接受什么样类型的参数类?

ArrayList?
ArrayList?
ArrayList?

显然ArrayList。
原因是:虽然Integer和Double是Number类型的子类,但是ArrayList和ArrayList类型并不是ArrayList类型的子类。

在泛型里也存在子类型,前提是其泛型参数的限制并没有发生改变,或者说泛型没有改变。其实就是从原来的类或接口来判断泛型的子类型。

比如ArrayLIst implements List,而List extends Collection,那么ArrayList就是List的子类型,而List又是Collection的子类型。

泛型参数界限与通配符

有时候,你会希望泛型类型只能是某一部分类型,比如在操作数据的时候,你希望是Number或其子类类型。这个通常的做法就是给泛型参数添加一个参数。其定义的形式为:

<T extends ParentType>

这个定义表示T应该是Numner的子类型,T和Parant可以是类,也可以是接口,注意此处的extends表示的是ParentType的子类型,和继承是有区别的。

public class Box<T> {
 
    private T t;
 
    public void set(T t) {
 
        this.t = t;
 
    }
 
    public T get() {
 
        return t;
 
    }
 
    public <U extends Number> void inspect(U u) {
 
        System.out.println("T: " + t.getClass().getName());
 
        System.out.println("U: " + u.getClass().getName());
 
    }
 
    public static void main(String[] args) {
 
        Box<String> integerBox = new Box<>();
 
        integerBox.set("abc"); //能通过编译,因为T指定为String类型
 
        // integerBox.inspect("abc");//不能通过编译,因为U必须是Number类型或其子类
 
        integerBox.inspect(new Integer(10));
 
    }
 
}

对象关系

关联

面向对象高级编程 全课程_第24张图片

组合

面向对象高级编程 全课程_第25张图片

聚合

面向对象高级编程 全课程_第26张图片

依赖

面向对象高级编程 全课程_第27张图片

其他特征

原始类型的装箱和拆箱

什么是装箱?什么是拆箱?

Java为每种基本数据类型都提供了对应的包装器类型。
在Java SE5之前,如果要生成一个数值为10的Integer对象,必须这样进行:

Integer i = new Integer(10);

而在从Java SE5开始就提供了自动装箱的特性,如果要生成一个数值为10的Integer对象,只需要这样就可以了:

Integer i = 10;

这个过程中会自动根据数值创建对应的 Integer对象,这就是装箱。

那什么是拆箱呢?顾名思义,跟装箱对应,就是自动将包装器类型转换为基本数据类型:

Integer i = 10;  //装箱
int n = i;   //拆箱

简单一点说,装箱就是 自动将基本数据类型转换为包装器类型;拆箱就是 自动将包装器类型转换为基本数据类型。

1、实体中数值类型一般定义为包装类型
2、接受参数推荐定义为包装类型
目的:避免null导致程序异常。

装箱和拆箱是如何实现的
public class Main {

    public static void main(String[] args) {
        Integer i = 10;
        int n = i;
    }
}

装箱过程是通过调用包装器的valueOf方法实现的,而拆箱过程是通过调用包装器的 xxxValue方法实现的。(xxx代表对应的基本数据类型)。

面向对象高级编程 全课程_第28张图片

为什么使用ArrayList< Integer >?

集合元素不支持原始数据类型:ArrayList< int >,需要修改为ArrayList< Integer >。

final类是什么?

面向对象高级编程 全课程_第29张图片
包装类为final类型,表示该类不能被继承(扩展)。
被包装的值value为final类型,表示初始化后不能被修改,这种类也称为immutable.

面向对象高级编程 全课程_第30张图片

枚举类

面向对象高级编程 全课程_第31张图片
参考博文:https://blog.csdn.net/zhou520yue520/article/details/80952404

内部类与匿名类(迭代器)

面向对象高级编程 全课程_第32张图片

lambda表达式
面向对象高级编程 全课程_第33张图片

反射与动态编程

面向对象高级编程 全课程_第34张图片

第二章 面向对象设计思想——设计原则与设计模式

设计原则

面向对象高级编程 全课程_第35张图片

其他原则

关注点分离面向对象高级编程 全课程_第36张图片
抽象原则

面向对象高级编程 全课程_第37张图片
面向对象高级编程 全课程_第38张图片

SOLID

职责分配原则

创造者模式

单例模式

原型模式

实验2 设计小游戏让人物跑起来

结构型模式

适配器模式

实验3 动图字幕编辑器

代理模式(动态代理)

实验6 带日志功能的计算器

行为型模式

状态模式

实验4 角色状态控制

职责链模式(迭代器)

实验5 基于职责链的计算器
实验5 支持迭代访问的整型列表

观察者模式

实验7 环境监控程序

第三章 Java核心技术

实验8 多线程与网络编程

你可能感兴趣的:(java面向对象,java,jvm,数据结构)