【Java】【阿里云大学】面向对象编程全套笔记(更新中)

  • 之前在阿里云大学公开课上学了一些Java面向对象编程,决定把笔记和代码更新下
  • 本文从面向对象编程开始记录(ps.阿里云老师讲的很有趣 = w =),阿里云大学Java网课网址链接

Java面向对象编程

第一章 类与对象

课时2:面向对象简介

面向过程面向对象
面对一个问题的解决方案更多情况是面对一个问题的解决方案模块化设计,可以重用配置

面向对象有三个主要特性:

  • 封装性:内部操作对外部不可见,当内部的操作都不可直接在外部使用时才是安全的;
  • 继承性:在已有结构的基础上继续进行功能的扩充;比如手机是围绕其通话功能进行扩充的。
  • 多态性:在继承性基础上扩充的概念,指的是类型的转化处理

面向对象开发的步骤:(由生活场景进行程序分析最好)

  • OOA:面向对象分析
  • OOD:面向对象设计
  • OOP:面向对象编程

课时3:类与对象简介

  • 区别每个事物的不同是根据其属性,每一个属性的集合构建出一个群体,这个抽象群体就是类;
  • 抽象群体的一个实际群体,就是类的实例化对象。
对象
某一类事物的抽象概念具体的产物
一个模板可以使用的模板实例

类中一般有两个组成:

  • 成员属性:比如一个人(事物)的年龄姓名(属性)
  • 操作方法:定义对象处理的行为,比如(事物)会唱、跳、rap(行为)

课时4:类与对象定义

Java中类是一个独立的结构体,所以需要用class来定义

public class Person {
	String name;//姓名属性
	int age;//年龄属性
	void tell() {//tell行为
		System.out.println("name" + name + "age" + age);
	}
}

有了类,如果需要产生对象:

  • 声明并实例化对象:类名称 对象名称 = new 类名称(属性参数)
  • 分步骤完成:
    声明对象:类名称 对象名称 = null;
    实例化对象:对象名称 = new 类名称();

有了对象需要调用对象:

  • 调用属性:实例化对象.对象属性;
  • 调用方法行为:实例化对象.方法名称(需要传给方法行为的参数);

例子如下:

public class C4Person {
	public static void main(String args[])
	{
		Person per = new Person();//声明实例化对象
		per.name = "Tom";
		per.age = 3;
		per.tell();//方法的调用
	}
}

如果并没有进行对象的属性内容设置,则属性内容为属性的默认值(String:null int:0)

课时5:对象内存分析

Java中类属于引用数据类型,困难之处在于要进行内存的管理。所以对内存管理进行一下分析。

  • 通过栈内存找到堆内存,子啊找到对象的具体信息
堆内存栈内存
保存的是对象的具体信息,在程序中堆内存的空间开辟由new完成一块堆内存的地址

new的内存分配

  • 课时4的内存分析(声明并实例化对象):
    在这里插入图片描述
  • 分步骤完成对象
    分步骤完成对象
    所有调用类的属性和方法在实例化对象完成后才能执行
  • 错误代码:
    没有实例化
    只是声明了对象但是没有实例化,(栈内存没有指向堆内存的指针,以及堆内存没有开辟,只有引用数据类型有此报错!!!,调用后会报NullPointerException空指针异常

课时6:对象引用分析

既然类本身属于引用数据类型,就牵扯到内存的引用传递,可以被不同的栈内存指向,也可以更换指向。

  • 引用传递示例
    引用传递示例
    内存分析
  • 通过方法的引用传递:
    与之前的差别最大的地方在于,此时的程序是将Person类的实例化对象(内存地址、属性的参数)传递到了change()方法中,由于传递的是一个Person对象类型,那么change()接收的也是Person类型。通过方法的引用传递
    在这里插入图片描述
  • 引用传递可以发生在方法上,要观察方法里面传的的参数类型,同时也要观察方法的执行过程。

课时7:引用传递与垃圾产生分析

所有的引用传递的本质是一场堆内存的调戏游戏,那么也会造成辣鸡的产生,针对辣鸡产生原因产生简单分析:

  • 一个成功的引用传递
    辣鸡分析
    辣鸡分析
  • 此时原本per2的堆内存空间没有栈内存的指向了,(变成了辣鸡)
  • 所有的辣鸡都被GC(Garbage Collector)收集器不定期回收并且释放内存空间
  • 辣鸡越多会影响GC的处理性能
  • 一个栈内存只能保存一个堆内存的地址数据,如果发生更改,则之前的地址数据将从此栈内存中彻底消失

第二章 深入分析类与对象

课时8:成员属性封装

在类之中的组成就是属性与方法,一般而言方法都是对外提供服务的,需要有较高的安全性,需要进行保护,需要采用封装性对属性进行保护。

  • 反例:类内部属性不封装时,类外部能修改属性
    在这里插入图片描述

  • 封装后,类外部不能访问其属性,但是对类内部可见。
    下面代码会报错,因为进行了类外部不能访问类内部封装好的属性
    在这里插入图片描述

  • 【setter、getter】设置或取得属性可以使用setXxx()、getXxx()方法

  • private String name为例

  • 设置属性方法public void setName(String n)

  • 获取属性方法public String getName()
    在这里插入图片描述
    在这里插入图片描述

  • 在需要对传入属性的获取判断时,在setXxx()里面添加条件判断闭并进一步修改值

set判断

  • 类中的所有属性都必须使用private封装
  • 访问属性必须setXxx() getXxx()

课时9:构造方法与匿名对象

现在的程序在使用类的时候一般都按照了如下的步骤进行:

  • 声明并实例化对象,这个时候实例化对象中的属性并没有任何的的数据存在,都是其对应数据类型的默认值
  • 需要通过一系列的**setter()**方法设置属性值

传统调用:在这里插入图片描述
这样的调用很麻烦,每次都要setter getter,所以可以通过构造方法实现实例化对象中的属性初始化处理,只有在关键字new的时候使用构造方法。

  • 构造方法名称必须与类名称保持一致
  • 构造方法不允许设置任何返回值类型,没有返回值定义
  • 构造方法时关键字new实例化对象的时候自动调用的
    在这里插入图片描述
Person per = new Person("Tom",18);//调用有参构造
  • 每个类都会提供构造方法,如果没有定义构造方法,那么默认的是无参的构造方法,是程序编译的时候自动创建的。
  • 如果这个类的构造方法已经明确在类中定义了,那么这个默认的构造方法将不会被自己创建。比如类中明确定义了有参,但是类外调用的是无参构造,那么就会报构造器参数的错。

疑问为什么构造方法不设置返回值类型;如果不返回数据,为什么不用void定义方法呢?

  • 编译器是根据代码结构进行编译的(突然想学《编译原理》),执行的时候也是根据代码结构执行。
  • 如果是void,那么此结构就与普通方法定义相同了,编译器会认为跟普通方法是一样的。
  • 然而构造方法是实例化对象的是时候调用的,而普通方法是对象产生之后调用的。

构造方法重载

升序或降序定义构造函数:在这里插入图片描述

构造方法setter getter
在实例化对象的时候设置对象的属性除了拥有设置属性的功能,还有修改属性的功能

实例化对象的创建步骤:

  1. 定义对象名称: 类名称 对象名称 = null
  2. 实例化对象:对象名称 = new 类名称()

所以:只通过实例化对象进行类的操作也是可以的,这种形式的对象叫做匿名对象

new Person("Tom",18).tell();

以上代码通过对象进行了tell()方法的调用,但是没有任何的引用,所以使用过后会变成内存辣鸡,将被GC进行辣鸡回收与释放。

以下代码显示了构造方法(只要是方法)能传递数据类型(包括类)

class Message{
	private String title;
	public Message(String t) {
		title = t;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String t) {
		title = t;
	}
}
class Person{
	private String name;
	private int age;
	public Person(Message msg,int a ) {
		name = msg.getTitle();
		age = a;
	}
	public Message getInfo(){
		return new Message(name + ":" + age)
	}
	public void tell() {
		System.out.println("姓名" + name + "年龄" + age);
	}
}
public class No1PersonMessage {
	public static void main(String args[]) {
		Message msg = new Message("mldn");
		Person per = new Person(msg,20);
		msg = per.getInfo();
		System.out.println(msg.getTitle());
	}	
}

在这里插入图片描述

第三章 this关键字

课时10:this调用本类属性

this有三类结构

  • 当前类中的属性this.属性
  • 当前类中的方法(普通方法,构造方法):this(),this.方法名称();
  • 描述当前对象

setter getter方法可以对属性进行赋值,但是在赋值的时候,采用的是如下的格式:
在这里插入图片描述
在Java程序之中“{ }”是作为结构体的边界符,那么在程序里面进行变量(参数、属性都成为变量)使用的时候都会以“{ }”作为一个查找边界(作用域),按照就近取用的原则,此时的构造方法并没有能够访问类中的属性,所以为了明确标记类中的属性和参数的区别,往往会在属性前追加一个this,表示本类的属性。
所以只要是访问本类中的属性的时候,都要加this

public Person(String n,int a) {
	this.name = n;
	this.age = a;
}
public void tell() {
	System.out.println("姓名:" + this.name + "、年龄:" + this.age);
}

课时11:this调用本类方法

  • 构造方法调用:this.()使用关键字new实例化对象的时候才会调用构造方法
  • 普通方法调用:this.名称() 实例化对象产生之后就可以调用普通方法
    构造方法调用this.setter方法 实现属性赋值
    在这里插入图片描述
    构造方法的调用
  1. 传统做法:

构造方法调用
如果要评价一个代码的好坏:

  • 代码结构可以重用,提供的是一个中间独立的支持;
  • 目标是没有重复的属性

所以:

  • 利用this构造进行调用
    在这里插入图片描述
    对于本类狗仔方法的互相调用需要注意以下几个重要的问题:
  • 构造方法必须在实例化新对象的时候调用,所以this()只允许在构造函数的首行
  • 构造方法调用的时候必须要有出口(不要弄成死循环递归构造器调用)

课时12:简单Java类

简单Java类指的是可以描述某一类信息的程序类,并且在这个类中没有特别复杂的逻辑操作,只作为一种信息存储的媒介存在。

  • 类名称一定要有意义,能够描述某一类事物
  • 类之中的所有属性必须实现private进行封装,同时封装后的属性必须要提供有setter、getter
  • 类之中可以提供有无数个构造方法,但是必须要保留无参的构造方法
  • 类之中不允许出现任何输出语句,所有内容的获取必须返回。
  • 【非必须】可以提供有一个获取对象详细信息的方法,暂时将此方法名称定义为getInfo()

以下代码融合了到目前为止接触的概念:数据类型划分、类的定义、private封装、构造方法、方法定义、对象实例化

class Dept{
	private long deptno ;
	private String dname ;
	private String loc ;
	public Dept() {}//必须提供有无参
	public Dept(long deptno,String dname,String loc) {
		this.deptno = deptno ;
		this.dname = dname ;
		this.loc = loc ;
	}
	public String getInfo() {
		return "[部门信息] 部门编号:" + this.deptno +"、部门名称:" + this.dname + "、部门地址:" + this.loc ;
	}
	public void setDeptno(long deptno) {
		this.deptno = deptno ;
	}
	public void setDname(String dname) {
		this.dname = dname ;
	}
	public void setLoc(String loc) {
		this.loc = loc ;
	}
	public long getDeptno(){
		return this.deptno ;
	}
	public String getDname() {
		return this.dname ;
	}
	public String getLoc() {
		return this.loc ;
	}
}
public class No1Class{
	public static void main(String args[]) {
		Dept dept = new Dept(10,"技术部","北京");
		System.out.println(dept.getInfo());
	}
}

第四章:static关键字

课时13:声明static属性

在一个类中,所有的属性以但定义了实际上内容都交由各自的堆内存空间保存。
在这里插入图片描述

  • 在正常开发过程之中每一个对象都保存有各自的属性,所以此时的程序没有任何问题,但是当有一天country变成了中华人民共和国。并且你已经产生了5000w个对象,那么要一个一个的修改对象的属性,这是不可能的,因为重读保存数据并且修改不方便。
  • 所以要将country修改成一个公共属性,比如要用static定义。
static String country = "中华人民共和国"

static全局数据区

  • 但是对于static属性的访问要注意:由于其本身是一个公共的属性,虽然可以通过对象进行访问,但是要通过所有对象的最高代表(类)来访问,所以static名称可以由类名称直接调用
    所以:
Person.country = "中华人民共和国";

static虽然在类中,但是不受到实例化对象的控制。
static属性可以在没有实例化对象的时候使用

  • 例如以下代码:
    在这里插入图片描述
  • 以后在类设计的时候首选的一定是非static属性(95%),而考虑到公共信息存储的时候会使用到static属性(5%)。
  • 非static属性必须在实例化对象产生之后才可以使用,而static属性可以在没有实例化对象产生的情况下直接通过类名称进行调用。

课时14:声明static方法

static也可以定义方法,也可以通过类名称在没有实例化对象的时候调用

static方法非static方法
只!允许调用static属性允许调用static属性或者static方法
  • 错误示例:
    这里name会报错,因为static方法调用了非static属性name
    在这里插入图片描述
    为什么会报错?
    因为static定义的属性和方法在没有实例化的对象的前提下使用,而所有的非static实例化对象之后才能使用。如果在static方法下调用非static属性,因为还没有实例化对象,所以调用失败。使用this关键字也是一样会调用失败

  • 当前定义的方法都是在主类定义的,并且由主方法直接调用:
    在这里插入图片描述

  • 如果static要调用非static的话必须要先实例化对象产生一个非static属性或方法

在这里插入图片描述

  • 只有在回避实例化对象调用并且描述公共属性的情况下才考虑用static

课时15:static应用案例:

static可以实现类的统计操作,比如创建了几个实例化对象,对象的属性情况如何

  • 如下:每一次创建一个新的对象都要实现一个统计操作
class Book{
	//每一次创建一个新的对象都要实现一个统计操作
	private String title ;
	private static int count = 0 ;//
	public Book(String title) {
		this.setTitle(title) ;
		count ++;
		System.out.println("第" + count +"本新图书创建出来。") ;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
}
public class No2Book {
	public static void main(String args[]) {
		new Book("Java");
		new Book("JSP");
		new Book("Spring");
	}
}
  • 统计属性某种情况下的个数:如果现在传递了title属性,就使用传递的属性内容
    而如果没有传递title属性,则自动采用“NOTITLE-编号”的形式进行该属性的内容的定义
//如果现在传递了title属性,就使用传递的属性内容
//而如果没有传递title属性,则自动采用“NOTITLE-编号”的形式进行该属性的内容的定义
class BookPro{
	private String title ;
	private static int count = 0 ;
	public BookPro() {
		this("NOTITLE - " + count ++);
	}
	public BookPro(String title) {
		this.title = title ;
	}
	public String getTitle() {
		return this.title ;
	}
}
public class No3Book2 {
	public static void main(String args[]) {
		System.out.println(new Book("Java"));//匿名对象
		System.out.println(new Book("Jsp"));
		System.out.println(new Book("Spring"));
		System.out.println(new BookPro().getTitle());//无参构造
		BookPro pro = new BookPro();//证明类和实例化对象其实都可以
		System.out.println(pro.getTitle());
	}
}

第五章 代码块

课时16:普通代码块

在程序使用 “ { } ” 定义的结构就称为代码块,而后根据代码块出现的位置以及定义的不同,可以分为普通代码块、构造块、静态块、同步代码块,其中对于同步代码块在多线程的时候再使用。

  • 普通代码块:
    在这里插入图片描述
  • Java中规定相同的变量是不能够在同一个方法中存在的,但是由于此时有不同的分界描述,所以是可以的;
  • 可以在一个方法中进行一些结构的划分,以防止相同变量名称所带来的互相影响。

课时17:构造代码块

构造块是定义在一个类之中的。

  • 构造块优先于构造方法执行,并且每一次实例化新对象的时候都会调用构造块中的代码。
    在这里插入图片描述
    在这里插入图片描述

课时18:静态代码块

静态代码块主要指的是使用static关键字定义的代码块,静态块的定义需要考虑到两种情况:主类中定义静态块、非主类定义静态块

  • 静态代码块会优先于构造块执行,并且不管由多少个实例化对象出现,静态代码块只会执行一次,静态代码块的主要目的是为类中的静态属性初始化。

在这里插入图片描述
在这里插入图片描述
下面通过静态代码块进行静态属性的初始化
在这里插入图片描述

  • 主类中的静态代码块优先于主方法先执行
    在这里插入图片描述
******程序初始化******
www.mldn.cn

第6章 面向对象案例分析

课时19 案例分析一(Address)

  • 需求:写一个Address类,地址由国家、省份、城市、街道、邮编组成。

😂因为太简单这里就写一下实现思想。
首先是地址参数用private XXX封装,然后构造空的构造函数,和含参的构造函数,有参的构造函数里面进行this.XXX = XXX赋值。然后每个参数都要public void setXXX(XXX)public XXX getXXX() 操作,然后再创建一个方法public XXX getInfo()来返回对象的参数。主函数里面直接System.out.println( new 对象名称(参数).getInfo());

  • 因为只是print所以这边就直接new了

课时20 案例分析二(Employee)

需求:实现员工的工资金额。员工属性:编号、姓名、基本薪水、薪水增长率。
属性设置和返回对象的参数跟之前课时19的实现方式一样,这里就不用说明。

  • 因为后面要进行运算,所以这里不直接加new了,而是先声明一个对象Employee emp = new Employee(参数)
  • 计算直接System.out.println("字符串" + emp.参数.....);

课时21 案例分析三(Dog)

需求:实现一个Dog类,有名字、年龄、颜色等属性。
课时19是一样的。主要是一个属性设置分析。

课时22 案例分析四(Account)

需求:构造一个银行账户类,包含:账户名称 账户余额,开户方法(设置账号名称及余额),查询余额。
属性设置和课时19一样。

  • 构造函数采用双参构造或者多参,因为开户的时候可能要考虑只设置了一个账户信息

课时23 案例分析五(User)

需求:设计一个表示用户的user类,类中的变量有用户名、口令和记录用户个数的变量,并赋值,获取和设置口令的方法和返回类信息的方法。

class User{
    private String uid;
    private String password;
    private static int count = 0;
    public User(){
        this("Noid","NULL");
    }
    public User(String uid){
        this(uid,"NULL");
    }
    public User(String uid,String password){
        this.uid = uid;
        this.password = password;
        count ++;
    }


    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getUid() {
        return uid;
    }

    public void setUid(String uid) {
        this.uid = uid;
    }

    public String getInfo(){
        return "用户名:" + this.uid + "、密码:" + this.password;
    }

    public static int getCount(){
        return count;
    }
}
public class C23User{
    public static void main(String[] args){
        User userA = new User();
        User userB = new User("zht");
        User userC = new User("zht","123456");
        System.out.println(userA.getInfo());
        System.out.println(userB.getInfo());
        System.out.println(userC.getInfo());
        System.out.println("用户个数:" + User.getCount());
    }
}

课时24 案例分析六(Book)

声明一个图书类,其数据成员为书名、编号(利用静态变量实现自动编号)、书价,并拥有数据成员册数、记录图书的总册数,在构造方法中利用此静态变量为对象的编号赋值,在主方法中定义多个对象,并求出总册数。

在这里插入代码片

Java语言高级特性

课时2:进程与线程

进程线程
操作系统上的划分进程上的划分(启动速度比进程快)

😜进程:

传统的DOS采用的是单进程处理,到了windows时代开启了多进程设计,于是一个时间段上可以同时运行多个程序,这些程序有资源的轮流抢占,(在操作系统中,我们有时间片轮转的调度算法如下解释),所以在一个时间线上会有多个程序依次执行,但是在一个时间点上,只会有一个进程执行,但是cpu多了,即使有再多的进程出现,也可以比单核cpu处理的速度快。

时间片轮转调度算法是非常公平的处理机分配方式,让就绪队列的每个进程每次仅运行一个时间片。
java实现进程调度策略(时间片轮转、最高优先级)

  • 😝 时间片轮转调度算法的基本原理

    系统根据先来先服务的原则,将所有的就绪进程排成一个就绪队列,并且每隔一段时间产生一次中断,激活系统中的进程调度程序,完成一次处理机调度,把处理机分配给就绪队列队首进程,让其执行指令。当时间片结束或进程执行结束,系统再次将cpu分配给队首进程。

  • 😀进程切换时机

  1. 时间片尚未结束,进程已经执行结束,立即激活调度程序,将其从就绪队列中删除,在调度就绪队列的队首进程执行,开启新的时间片(计数器置0)。
  2. 时间片已经结束,进程尚未结束,立即激活进程调度程序,未执行完的进程放到就绪队列的队尾。

😛时间片大小的确定

在轮转调度算法中时间片的大小对系统的性能有很大的影响若时间片很小,将有利于短作业,其能够在这个时间片内完成。时间片过小意味着会进行频繁的进程切换,这将增大系统的开销。若时间片选择太长时间片轮转调度算法将退化为先来先服务的进程调度算法

😜线程:

在进程基础上的划分, 比进程更小的程序单元,在进程基础上创建并使用的。启动速度比进程快。
Java是多线程的编程语言,在并发访问过程中能够更高效。

课时3:Thread类实现多线程

继承Thread类实现多线程

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值