一、面向对象和面向过程的关系
1)面向过程:强调的是功能行为,以函数为最小单位,考虑怎么做;
2)面向对象:强调了具备功能的对象,以类/对象为最小单位,考虑谁来做。
总结一手:
不管是面向过程、面向对象,都是程序设计的思路。
- 面向过程( Process Oriented Programming ,简称 POP ):以函数为基本单位,适合解决简单问 题。 - 面向对象( Object Oriented Programming ),简称 OOP ):以类为基本单位。适合解决复杂问题。二、Java类/类成员
1-概述
Java 类以及类的成员:属性、方法、构造器;代码块、内部类 面向对象的四大特征 : 封装性、继承性、多态性、(抽象性) 其他关键字: this 、 super 、 static 、 final 、 abstract 、 interface 、 package2-类和对象的关系
面向对象程序设计的重点就是类的设计;类的设计其实就是类的成员的设计。3-对象的创建与使用
面向对象完成具体功能的操作的三步流程: • 步骤 1 :创建类,并设计类的内部成员(属性、方法)。 • 步骤 2 :创建类的对象。如: Phone p1 = new Phone() 。 • 步骤 3:通过对象,调用其 内部声明的属性或方法,完成相关的功能。 匿名对象 (anonymous object ): • 我们也可以不定义对象的句柄,而直接调用这个对象的方法。 这样的对象叫做匿名对象。 • 如:new Person().shout(); • 使用情况: ◦ 如果一个对象只需要进行一次方法调用,那么就可以使用匿名对象。 ◦ 我们经常将匿名对象作为实参传递给一个方法调用。4-对象的内存解析
5-类的成员之一属性(成员变量field)
6-类的成员之二:方法(method)
public class Person {
private String name; // 字符串类型的 name 属性
private int age; // 整数类型的 age 属性
// get 方法用于获取 name 属性值
public String getName() {
return name;
}
// set 方法用于设置 name 属性值
public void setName(String name) {
this.name = name;
}
// get 方法用于获取 age 属性值
public int getAge() {
return age;
}
// set 方法用于设置 age 属性值
public void setAge(int age) {
this.age = age;
}
}
get set
可以用快捷键
alt+insert
进行设置
public class Test {
public void show(int i) {
System.out.println("show(int)");
}
public void show(String s) {
System.out.println("show(String)");
}
public void show(String... strs) {
System.out.println("show(String...)");
for (int i = 0; i < strs.length; i++) {
System.out.println(strs[i]); // 遍历可变参数数组
}
}
public static void main(String[] args) {
Test test = new Test();
test.show(5);
test.show("hello");
test.show("hello", "world");
test.show();
test.show(new String[]{"AA", "BB", "CC"});
}
}
7-类的成员之三:构造器
构造器的作用(也可以叫构造方法) 1创建对象,搭配 new 2.初始化对象的信息(成员变量) 如果没有显式的定义类的构造器的话,则系统默认提供一个空参的构造器(默认构造器的权限和类权限 相同) 定义构造器的格式: 权限修饰符 类名(形参列表){ } 一个类中定义的多个构造器,彼此之间构成重载 一旦我们显示的定义了类中的构造器之后,系统就不再提供默认的空参构造器 一个类中,至少会有一个构造器8-类的成员之四:代码块
1 )构造代码块 内部 有输出语句 且随着对象而创建 每创建一个对象,就执行一次构造代码块 作用:可以在创建对象时,对对象的属性可以初始化 如果一个类中定义了多个构造代码块,按照声明的先后顺序执行 构造代码块可以调用静态的属性、静态的方法,或非静态的属性和方法9-类的成员之五-内部类
成员内部类(静态/非静态)
局部内部类
内部类总结:匿名内部类
10-Java Bean
11-Java UML
1)什么是UML?
1、UML(统一建模语言),是一种用于软件系统分析和设计的语言工具,用于帮助软件开发人员进行思考和记录思路的结果。
2、UML本身是一套符号的规定,就像数学符号和化学符号一样,这些符号用于描述软件模型中的各个元素和它们之间的关系,如类、接口、实现、泛化、依赖、组合、聚合等。
2)UML的分类
1、用例图
2、静态结构图:类图、对象图、包图、组件图、部署图。
3、动态行为图:交互图(时序图与协作图)、状态图、活动图。
类图:描述类与类之间的关系,是UML图的核心。
3)UML 类图
1、用于描述类(对象)本身的组成和类(对象)之间的各种静态关系。
2、类之间的关系:依赖、泛化(继承)、实现、关联、聚合、组合。
类图示例代码
public class Person {
private Integer id;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
(1)依赖关系
只要在类中用到对方,它们之间就会存在依赖关系。
public class PersonServiceBean {
private PersonDao personDao;
public void save(Person person) {
}
public IDCard getIDCard(Integer personid){
return null;
}
public void modify(){
Department department = new Department();
}
}
public class IDCard {
}
public class Department {
}
public class Person {
}
public class PersonDao {
}
(2)泛化关系
泛化关系就是继承关系,是依赖关系的特例。
public abstract class DaoSupport {
public void save(Object entity){
}
public void delete(Object id){
}
}
public class PersonServiceBean extends DaoSupport {
}
(3)实现关系
实现关系就是一个接口被一个类实现了,是依赖关系的特例。
public interface PersonService {
public void delete(Integer id);
}
public class PersonServiceBean implements PersonService {
@Override
public void delete(Integer id) {
}
}
(4)关联关系
1、关联关系等同于类与类之间的联系,是依赖关系的特例。
2、关联具有导航性:就是双向关系和单向关系。
3、关联具有多重性
单向一对一关系:
public class IDCard {
}
public class Person {
private IDCard idCard;
}
(5)聚合关系
聚合关系表示整体和部分的关系,整体与部分可以分开。聚合关系是关联关系的特例,同样具有导航性和多重性。
public class Computer {
private Mouse mouse;
private Moniter moniter;
public void setMouse(Mouse mouse) {
this.mouse = mouse;
}
public void setMoniter(Moniter moniter) {
this.moniter = moniter;
}
}
public class Moniter {
}
public class Mouse {
}
(6)组合关系
整体与部分的关系,但是整体与部分不可以分开。
public class Computer {
private Mouse mouse = new Mouse();
private Moniter moniter = new Moniter();
public void setMouse(Mouse mouse) {
this.mouse = mouse;
}
public void setMoniter(Moniter moniter) {
this.moniter = moniter;
}
}
三、面向对象的三大特征
前置补充:要用到的关键字
( this package import super static final) --> 我们在通过子类的构造器创建对象时,一定在调用子类构造器的过程中,直接或间接的调用到父类的构造器。 也正因为调用过父类的构造器,我们才会将父类中声明的属性或方法加载到内存中,供子类对象使用。 1.概述:静态,关键字2.特点
被static修饰的成员随着类的加载而加载
被static修饰的成员由于跟着类到内存,所以优先于对象存在
被static修饰的成员属于子类成员,不属于对象成员(成员方法,成员变量)
根据static所在的类创建出来的对象,都会共享这个静态成员
3.使用
修饰成员变量 :static 数据类型 变量名
修饰方法:
修饰符 static 返回值类型 方法名(参数){
方法体
return 结果
}
4.使用: 类名直接调用
特性1-封装性
提供公共接口: getxxx ();获取属性值 setxxx ();为属性值复制1)空参构造
2)权限修饰符
3)有参构造
特性2-继承性
类图补充:抽象
【抽象类的介绍】 1.将多个类中共有的方法抽取到父类中,发现方法体没实现,所以将此方法定义成抽象方法,抽象方法 所在的类一定是抽象类 2.抽象关键字: abstract 3.抽象类 public abstrcat class 类名{ } 4.抽象方法: 修饰符 abstrcat 返回值类型 方法名(参数) 5. 注意 子类继承父类之后,必须要重写父类中所有的抽象方法 【抽象类的注意事项】 1)抽象类不能直接 new 对象,只能创建非抽象子类的对象 2)抽象类中,可以有构造方法,是供子类创建对象,初始化父类属性用的 3 )抽象类中可以有成员变量,构造,成员方法 4)抽象类中不一定非要有抽象方法,但是有抽象方法的类一定是抽象类 5)抽象类中的子类,必须重写父类中所有抽象方法,否则,编译无法通过(除非该子类 也是抽象类) 。package com.atguigu.b_abstract;
public abstract class Employee {
private String name; // 员工姓名
private int age; // 员工年龄
public Employee() {
}
public Employee(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;
}
/**
* 员工工作的抽象方法
*/
public abstract void work();
// public abstract void eat();
}
package com.atguigu.b_abstract;
public class Teacher extends Employee{
public Teacher() {
}
public Teacher(String name, int age) {
super(name, age);
}
@Override
public void work() {
System.out.println("讲师在讲课");
}
}
package com.atguigu.b_abstract;
public class Test {
public static void main(String[] args) {
Teacher t1 = new Teacher("涛哥", 16);
t1.work();
}
}
补充:接口
怎么定义接口 ?
1 定义一个接口 interface public interface 接口名{ } 2. 定义实现类接口: implements public class 类名 implements 接口名 3. 在实现类中重写接口中所有的抽象方法 package com . atguigu . b_abstract ; public class Test { public static void main ( String [] args ) { Teacher t1 = new Teacher ( " 涛哥 " , 16 ); t1 . work (); } } 4. 创建实现类对象(接口不能直接 new 对象),调用重写的方法 接口中的成员package com.atguigu.d_interface;
public interface USB {
public abstract void open();
abstract void close();
public default void sleep(){
System.out.println("USB休眠");
}
}
package com.atguigu.d_interface;
public class Mouse implements USB{
@Override
public void open() {
System.out.println("鼠标开启");
}
@Override
public void close() {
System.out.println("鼠标关闭");
}
}
package com.atguigu.d_interface;
public class Test01 {
public static void main(String[] args) {
Mouse mouse = new Mouse();//接口不能直接new对象
mouse.open();
mouse.close();
}
}
【默认方法:】
package com.atguigu.e_interface;
public class Mouse implements USB{
@Override
public void methodDef(){
System.out.println("我是重写的接口中的默认方法");
}
}
package com.atguigu.e_interface;
public interface USB {
//默认方法
public default void methodDef(){
System.out.println("我是接口中的默认方法");
}
//静态方法
public static void methodSta(){
System.out.println("我是接口中的静态方法");
}
}
package com.atguigu.e_interface;
public class Test01 {
public static void main(String[] args) {
Mouse mouse = new Mouse();
mouse.methodDef();
System.out.println("================");
USB.methodSta();
}
}
静态方法:
【接口:成员方法】
当一个类实现多个接口时,如果默认方法有重名的,参数一样,要重写一次 【接口和抽象类的区别】特性3-多态性
1)基本概念
package com.atguigu.h_duotai;
/**父类**/
public class Animal {
public void eat(){
System.out.println("动物要吃饭");
}
}
package com.atguigu.h_duotai;
/**子类1**/
public class Dog extends Animal{
/**有子类继承关系有方法重写**/
public void eat(){
System.out.println("狗啃骨头");
}
//特有方法
public void lookDoor(){
System.out.println("狗会看门");
}
}
package com.atguigu.h_duotai;
/** 子类2**/
public class Cat extends Animal{
/**有子类继承关系有方法重写**/
@Override
public void eat() {
System.out.println("猫吃鱼");
}
//特有方法
public void catchMouse(){
System.out.println("猫会抓老鼠");
}
}
package com.atguigu.h_duotai;
/**测试类**/
public class Test01 {
public static void main(String[] args) {
//原始方式new对象
Dog dog = new Dog();
dog.eat();
dog.lookDoor();
System.out.println("==========");
Cat cat = new Cat();
cat.eat();
cat.catchMouse();
System.out.println("=====以下是多态形式new=====");
//多态形式new对象
Animal animal = new Dog();
animal.eat();
//animal.lookDoor();//多态前提下,不能直接调用子类特有功能
//lookDoor是子类特有方法,不能直接调用,下述一样
System.out.println("=======");
Animal animal1 = new Cat();
animal1.eat();
//animal1.catchMouse();//多态前提下,不能直接调用子类特有功能
}
}
2)多态成员以及成员方法的访问特点
package com.atguigu.i_duotai;
public class Fu {
int num = 100;
public void method(){
System.out.println("父类中的method方法");
}
}
package com.atguigu.i_duotai;
public class Zi extends Fu{
int num = 10;
public void method(){
System.out.println("子类中的method方法");
}
}
package com.atguigu.i_duotai;
/****/
public class Test {
public static void main(String[] args) {
//多态方式new一个对象
Fu fu = new Zi();
//成员变量没有多态性,成员方法要是有重名的直接子类重写就行了
System.out.println(fu.num);//父类的100
fu.method();
System.out.println("============");
//原始方式
Zi zi = new Zi();
System.out.println(zi.num);//子类的10
zi.method();
}
}
输出:
100
子类中的method方法
============
10
子类中的method方法
3)多态的好处
4)多态的转型
package com.atguigu.k_duotai;
public class Test01 {
public static void main(String[] args) {
Dog dog = new Dog();
method(dog);
Cat cat = new Cat();
method(cat);
}
public static void method(Animal animal) {//Animal animal = Dog Animal animal = Cat
if (animal instanceof Dog){
animal.eat();
//向下转型
Dog dog = (Dog) animal;//强制从dog类转为animal
dog.lookDoor();//就可以调子类成员方法了
}
/***
* 向下转型容易出现的问题: classCastException----->类型转换异常
*
* 出现问题的原因: 转型的时候,等号左右两边型号不一致
*
* 解决方案:做判断
* 关键字:instanceof关键字------>用来判断某个对象是否属于某种数据类型。 返回值为布尔类型
* 格式:
* 对象名 instanceof 类型--》关键字前面的类型是否属于关键字后面的类型
*
* */
if (animal instanceof Cat){
animal.eat();
Cat cat = (Cat) animal;
cat.catchMouse();
}
}
}
多态练习
2)分析
3)代码实现
package com.atguigu.l_duotai;
/**
* -USB接口类,包括开启功能、关闭功能
* **/
public interface USB {
void open();//不写abstract也可以
void close();
}
package com.atguigu.l_duotai;
public class KeyBoard implements USB{
//重写接口方法
@Override
public void open() {
System.out.println("键盘开启");
}
@Override
public void close() {
System.out.println("键盘关闭");
}
}
package com.atguigu.l_duotai;
/**Mouse类**/
public class Mouse implements USB{
@Override
public void open() {//重写接口方法
System.out.println("鼠标开启");
}
@Override
public void close() {
System.out.println("鼠标关闭");
}
}
package com.atguigu.l_duotai;
public class NoteBook {
public void start(){//成员方法
System.out.println("开机了");
}
/**
* 接收TEST类传过来的Mouse对象
*USB接收
* USB是mouse的接口类型 USB usb = mouse
* mouse是usb的接口实现类对象
* 接口看成父类。接口实现类看成子类
* 多态的体现
* **/
public void useUSB(USB usb){
// USB usb = keyBoard
usb.open();//多态调用
usb.close();
}
public void stop(){
System.out.println("关机了");
}
}
package com.atguigu.l_duotai;
/**
* 定义笔记本类,具备开机,关机和使用USB设备的功能,具体是什么USB设备,笔记本不关心,
* 只要符合USB规格的设备都可以。鼠标和键盘要想在电脑上使用,
* 那么鼠标和键盘也必须遵守USB规范,不然鼠标和键盘的生产出来无法使用
* 描述笔记本类,实现笔记本使用USB鼠标、USB键盘
*
* -USB接口,包括开启功能、关闭功能
* -笔记本类,包含运行功能、关机功能、使用USB功能
* -鼠标类,要符合USB
* -键盘类,要符合USB接口
*
* **/
public class Test01 {
public static void main(String[] args) {
NoteBook noteBook = new NoteBook();
noteBook.start();//笔记本类调用笔记本类的成员方法开机
Mouse mouse = new Mouse();
noteBook.useUSB(mouse);//传了一个mouse对象给接口实现类Mouse
System.out.println("==================");
KeyBoard keyBoard = new KeyBoard();
noteBook.useUSB(keyBoard);
noteBook.stop();
}
}
object类
1)使用object接收所有类
class Person {}
class Student {}
public class Test {
public static void main(String[] args) {
Object per = new Person();
Object stu = new Student();
}
}
2)object类的结构图
下面我们一个个方法进行分析,看这些方法到底有什么作用: 1. clone() 保护方法,实现对象的浅复制,只有实现了Cloneable 接口才可以调用该方法,否则抛出 CloneNotSupportedException 异常。 2. getClass() final方法,返回 Class 类型的对象,反射来获取对象。 3. toString() 该方法用得比较多,一般子类都有覆盖,来获取对象的信息。 4. finalize() 该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用。 5. equals() 比较对象的内容是否相等 6. hashCode() 该方法用于哈希查找,重写了equals 方法一般都要重写 hashCode 方法。这个方法在一些具有哈希功能 的 Collection 中用到。 7. wait() wait方法就是使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。 wait() 方法一直等待,直到获得锁或者被中断。 wait(long timeout) 设定一个超时间隔,如果在规定时间 内没有获得锁就返回。 调用该方法后当前线程进入睡眠状态,直到以下事件发生。 其他线程调用了该对象的notify 方法。 其他线程调用了该对象的notifyAll 方法。 其他线程调用了interrupt 中断该线程。 时间间隔到了。 此时该线程就可以被调度了, 如果是被中断的话就抛出一个InterruptedException异常。 8. notify() 该方法唤醒在该对象上等待的某个线程。 9. notifyAll() 该方法唤醒在该对象上等待的所有线程。
3)object类的常用方法
(1)toString方法
toString() :取得对象信息,返回该对象的字符串表示 我们先看一个简单的例子:class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Test {
public static void main(String[] args) {
Person per = new Person("Mr.Q", 20);
System.out.println(per);
}
}
输出:
iqqcode.algorithm.bintree.Person@1ee12a7
在使用对象直接输出的时候,默认输出的是一个对象在堆内存上的地址值;如若要输出该对象的内容,则要覆写
toString()
方法
覆写Person中的 toString() 方法 如下
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "名字为:" + this.name + ",年龄为:" + this.age;
}
}
public class Test {
public static void main(String[] args) {
Person per = new Person("Mr.Q", 20);
System.out.println(per);
}
}
package com.atguigu.b_object;
import java.util.ArrayList;
public class Test01 {
public static void main(String[] args) {
Person p1 = new Person("柳岩",36);
Person p2 = new Person("涛哥",18);
System.out.println(p1);
System.out.println(p2);
System.out.println(p1.toString());//com.atguigu.b_object.Person@135fbaa4
System.out.println(p2.toString());//com.atguigu.b_object.Person@45ee12a7
ArrayList<String> list = new ArrayList<>();
list.add("abc");
list.add("def");
System.out.println(list);// [abc, def]
}
}
(2)equals方法
package com.atguigu.b_object;
public class Test02 {
public static void main(String[] args) {
// 创建两个Person对象,内容相同
Person p1 = new Person("柳岩",36);
Person p2 = new Person("柳岩",36);
// 使用equals方法比较p1和p2,期望结果是false
//System.out.println(p1.equals(p2));//false
// 使用equals方法比较p1和ArrayList对象,期望结果是false
//ArrayList<String> list = new ArrayList<>();
//System.out.println(p1.equals(list));
// 使用equals方法比较p1和null,期望结果是false
//System.out.println(p1.equals(null));
// 使用equals方法比较p1和自身,期望结果是true
System.out.println(p1.equals(p1));
System.out.println("=========================");
// 创建两个String对象,内容相同
String s1 = new String("abc");
String s2 = new String("abc");
// 使用equals方法比较s1和s2,期望结果是true
System.out.println(s1.equals(s2));//true
//equals重写 String方法内容 所以结果是true 但在实际内存中,内存的地址不一样
// 使用==比较s1和s2,期望结果是false
System.out.println(s1==s2);//false
}
}
/**
*
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 重写equals方法,通过name和age来判断两个Person对象是否相等
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
Person person = (Person) obj;
return age == person.age && name.equals(person.name);
}
}
*
*
* **/
@Override
public boolean equals(Object obj) {
// 判断是否为同一对象
if (this == obj) {
return true;
}
// 判断传入的对象是否为空或者是否属于要比较的类对象
if (obj == null || getClass() != obj.getClass()) {
return false;
}
// 向下转型,将 Object 类还原为 Person 类
Person person = (Person) obj;
// 比较 name 和 age 是否相等
return age == person.age && Objects.equals(name, person.name);
}
比较结果为 true 所以,引用类型的数据在进行比较时,应该先覆写 equals() 方法,不然比较的还是两个对象的堆内存地址值,必然不会相等.
(4)getclass方法和native方法
getclass方法
public class Person {
private String name;
private int age;
// 默认构造函数
public Person() {
}
// 带参数的构造函数
public Person(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;
}
// 重写toString方法
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
native方法
GC垃圾回收类简介
一、面向对象和面向过程的关系
1)面向过程:强调的是功能行为,以函数为最小单位,考虑怎么做;
2)面向对象:强调了具备功能的对象,以类/对象为最小单位,考虑谁来做。
总结一手:
不管是面向过程、面向对象,都是程序设计的思路。
- 面向过程( Process Oriented Programming ,简称 POP ):以函数为基本单位,适合解决简单问 题。 - 面向对象( Object Oriented Programming ),简称 OOP ):以类为基本单位。适合解决复杂问题。二、Java类/类成员
1-概述
Java 类以及类的成员:属性、方法、构造器;代码块、内部类 面向对象的四大特征 : 封装性、继承性、多态性、(抽象性) 其他关键字: this 、 super 、 static 、 final 、 abstract 、 interface 、 package2-类和对象的关系
面向对象程序设计的重点就是类的设计;类的设计其实就是类的成员的设计。3-对象的创建与使用
面向对象完成具体功能的操作的三步流程: • 步骤 1 :创建类,并设计类的内部成员(属性、方法)。 • 步骤 2 :创建类的对象。如: Phone p1 = new Phone() 。 • 步骤 3:通过对象,调用其 内部声明的属性或方法,完成相关的功能。 匿名对象 (anonymous object ): • 我们也可以不定义对象的句柄,而直接调用这个对象的方法。 这样的对象叫做匿名对象。 • 如:new Person().shout(); • 使用情况: ◦ 如果一个对象只需要进行一次方法调用,那么就可以使用匿名对象。 ◦ 我们经常将匿名对象作为实参传递给一个方法调用。4-对象的内存解析
5-类的成员之一属性(成员变量field)
6-类的成员之二:方法(method)
public class Person {
private String name; // 字符串类型的 name 属性
private int age; // 整数类型的 age 属性
// get 方法用于获取 name 属性值
public String getName() {
return name;
}
// set 方法用于设置 name 属性值
public void setName(String name) {
this.name = name;
}
// get 方法用于获取 age 属性值
public int getAge() {
return age;
}
// set 方法用于设置 age 属性值
public void setAge(int age) {
this.age = age;
}
}
get set
可以用快捷键
alt+insert
进行设置
public class Test {
public void show(int i) {
System.out.println("show(int)");
}
public void show(String s) {
System.out.println("show(String)");
}
public void show(String... strs) {
System.out.println("show(String...)");
for (int i = 0; i < strs.length; i++) {
System.out.println(strs[i]); // 遍历可变参数数组
}
}
public static void main(String[] args) {
Test test = new Test();
test.show(5);
test.show("hello");
test.show("hello", "world");
test.show();
test.show(new String[]{"AA", "BB", "CC"});
}
}
7-类的成员之三:构造器
构造器的作用(也可以叫构造方法) 1创建对象,搭配 new 2.初始化对象的信息(成员变量) 如果没有显式的定义类的构造器的话,则系统默认提供一个空参的构造器(默认构造器的权限和类权限 相同) 定义构造器的格式: 权限修饰符 类名(形参列表){ } 一个类中定义的多个构造器,彼此之间构成重载 一旦我们显示的定义了类中的构造器之后,系统就不再提供默认的空参构造器 一个类中,至少会有一个构造器8-类的成员之四:代码块
1 )构造代码块 内部 有输出语句 且随着对象而创建 每创建一个对象,就执行一次构造代码块 作用:可以在创建对象时,对对象的属性可以初始化 如果一个类中定义了多个构造代码块,按照声明的先后顺序执行 构造代码块可以调用静态的属性、静态的方法,或非静态的属性和方法9-类的成员之五-内部类
成员内部类(静态/非静态)
局部内部类
内部类总结:匿名内部类
10-Java Bean
11-Java UML
1)什么是UML?
1、UML(统一建模语言),是一种用于软件系统分析和设计的语言工具,用于帮助软件开发人员进行思考和记录思路的结果。
2、UML本身是一套符号的规定,就像数学符号和化学符号一样,这些符号用于描述软件模型中的各个元素和它们之间的关系,如类、接口、实现、泛化、依赖、组合、聚合等。
2)UML的分类
1、用例图
2、静态结构图:类图、对象图、包图、组件图、部署图。
3、动态行为图:交互图(时序图与协作图)、状态图、活动图。
类图:描述类与类之间的关系,是UML图的核心。
3)UML 类图
1、用于描述类(对象)本身的组成和类(对象)之间的各种静态关系。
2、类之间的关系:依赖、泛化(继承)、实现、关联、聚合、组合。
类图示例代码
public class Person {
private Integer id;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
(1)依赖关系
只要在类中用到对方,它们之间就会存在依赖关系。
public class PersonServiceBean {
private PersonDao personDao;
public void save(Person person) {
}
public IDCard getIDCard(Integer personid){
return null;
}
public void modify(){
Department department = new Department();
}
}
public class IDCard {
}
public class Department {
}
public class Person {
}
public class PersonDao {
}
(2)泛化关系
泛化关系就是继承关系,是依赖关系的特例。
public abstract class DaoSupport {
public void save(Object entity){
}
public void delete(Object id){
}
}
public class PersonServiceBean extends DaoSupport {
}
(3)实现关系
实现关系就是一个接口被一个类实现了,是依赖关系的特例。
public interface PersonService {
public void delete(Integer id);
}
public class PersonServiceBean implements PersonService {
@Override
public void delete(Integer id) {
}
}
(4)关联关系
1、关联关系等同于类与类之间的联系,是依赖关系的特例。
2、关联具有导航性:就是双向关系和单向关系。
3、关联具有多重性
单向一对一关系:
public class IDCard {
}
public class Person {
private IDCard idCard;
}
(5)聚合关系
聚合关系表示整体和部分的关系,整体与部分可以分开。聚合关系是关联关系的特例,同样具有导航性和多重性。
public class Computer {
private Mouse mouse;
private Moniter moniter;
public void setMouse(Mouse mouse) {
this.mouse = mouse;
}
public void setMoniter(Moniter moniter) {
this.moniter = moniter;
}
}
public class Moniter {
}
public class Mouse {
}
(6)组合关系
整体与部分的关系,但是整体与部分不可以分开。
public class Computer {
private Mouse mouse = new Mouse();
private Moniter moniter = new Moniter();
public void setMouse(Mouse mouse) {
this.mouse = mouse;
}
public void setMoniter(Moniter moniter) {
this.moniter = moniter;
}
}
三、面向对象的三大特征
前置补充:要用到的关键字
( this package import super static final) --> 我们在通过子类的构造器创建对象时,一定在调用子类构造器的过程中,直接或间接的调用到父类的构造器。 也正因为调用过父类的构造器,我们才会将父类中声明的属性或方法加载到内存中,供子类对象使用。 1.概述:静态,关键字2.特点
被static修饰的成员随着类的加载而加载
被static修饰的成员由于跟着类到内存,所以优先于对象存在
被static修饰的成员属于子类成员,不属于对象成员(成员方法,成员变量)
根据static所在的类创建出来的对象,都会共享这个静态成员
3.使用
修饰成员变量 :static 数据类型 变量名
修饰方法:
修饰符 static 返回值类型 方法名(参数){
方法体
return 结果
}
4.使用: 类名直接调用
特性1-封装性
提供公共接口: getxxx ();获取属性值 setxxx ();为属性值复制1)空参构造
2)权限修饰符
3)有参构造
特性2-继承性
类图补充:抽象
【抽象类的介绍】 1.将多个类中共有的方法抽取到父类中,发现方法体没实现,所以将此方法定义成抽象方法,抽象方法 所在的类一定是抽象类 2.抽象关键字: abstract 3.抽象类 public abstrcat class 类名{ } 4.抽象方法: 修饰符 abstrcat 返回值类型 方法名(参数) 5. 注意 子类继承父类之后,必须要重写父类中所有的抽象方法 【抽象类的注意事项】 1)抽象类不能直接 new 对象,只能创建非抽象子类的对象 2)抽象类中,可以有构造方法,是供子类创建对象,初始化父类属性用的 3 )抽象类中可以有成员变量,构造,成员方法 4)抽象类中不一定非要有抽象方法,但是有抽象方法的类一定是抽象类 5)抽象类中的子类,必须重写父类中所有抽象方法,否则,编译无法通过(除非该子类 也是抽象类) 。package com.atguigu.b_abstract;
public abstract class Employee {
private String name; // 员工姓名
private int age; // 员工年龄
public Employee() {
}
public Employee(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;
}
/**
* 员工工作的抽象方法
*/
public abstract void work();
// public abstract void eat();
}
package com.atguigu.b_abstract;
public class Teacher extends Employee{
public Teacher() {
}
public Teacher(String name, int age) {
super(name, age);
}
@Override
public void work() {
System.out.println("讲师在讲课");
}
}
package com.atguigu.b_abstract;
public class Test {
public static void main(String[] args) {
Teacher t1 = new Teacher("涛哥", 16);
t1.work();
}
}
补充:接口
怎么定义接口 ?
1 定义一个接口 interface public interface 接口名{ } 2. 定义实现类接口: implements public class 类名 implements 接口名 3. 在实现类中重写接口中所有的抽象方法 package com . atguigu . b_abstract ; public class Test { public static void main ( String [] args ) { Teacher t1 = new Teacher ( " 涛哥 " , 16 ); t1 . work (); } } 4. 创建实现类对象(接口不能直接 new 对象),调用重写的方法 接口中的成员package com.atguigu.d_interface;
public interface USB {
public abstract void open();
abstract void close();
public default void sleep(){
System.out.println("USB休眠");
}
}
package com.atguigu.d_interface;
public class Mouse implements USB{
@Override
public void open() {
System.out.println("鼠标开启");
}
@Override
public void close() {
System.out.println("鼠标关闭");
}
}
package com.atguigu.d_interface;
public class Test01 {
public static void main(String[] args) {
Mouse mouse = new Mouse();//接口不能直接new对象
mouse.open();
mouse.close();
}
}
【默认方法:】
package com.atguigu.e_interface;
public class Mouse implements USB{
@Override
public void methodDef(){
System.out.println("我是重写的接口中的默认方法");
}
}
package com.atguigu.e_interface;
public interface USB {
//默认方法
public default void methodDef(){
System.out.println("我是接口中的默认方法");
}
//静态方法
public static void methodSta(){
System.out.println("我是接口中的静态方法");
}
}
package com.atguigu.e_interface;
public class Test01 {
public static void main(String[] args) {
Mouse mouse = new Mouse();
mouse.methodDef();
System.out.println("================");
USB.methodSta();
}
}
静态方法:
【接口:成员方法】
当一个类实现多个接口时,如果默认方法有重名的,参数一样,要重写一次 【接口和抽象类的区别】特性3-多态性
1)基本概念
package com.atguigu.h_duotai;
/**父类**/
public class Animal {
public void eat(){
System.out.println("动物要吃饭");
}
}
package com.atguigu.h_duotai;
/**子类1**/
public class Dog extends Animal{
/**有子类继承关系有方法重写**/
public void eat(){
System.out.println("狗啃骨头");
}
//特有方法
public void lookDoor(){
System.out.println("狗会看门");
}
}
package com.atguigu.h_duotai;
/** 子类2**/
public class Cat extends Animal{
/**有子类继承关系有方法重写**/
@Override
public void eat() {
System.out.println("猫吃鱼");
}
//特有方法
public void catchMouse(){
System.out.println("猫会抓老鼠");
}
}
package com.atguigu.h_duotai;
/**测试类**/
public class Test01 {
public static void main(String[] args) {
//原始方式new对象
Dog dog = new Dog();
dog.eat();
dog.lookDoor();
System.out.println("==========");
Cat cat = new Cat();
cat.eat();
cat.catchMouse();
System.out.println("=====以下是多态形式new=====");
//多态形式new对象
Animal animal = new Dog();
animal.eat();
//animal.lookDoor();//多态前提下,不能直接调用子类特有功能
//lookDoor是子类特有方法,不能直接调用,下述一样
System.out.println("=======");
Animal animal1 = new Cat();
animal1.eat();
//animal1.catchMouse();//多态前提下,不能直接调用子类特有功能
}
}
2)多态成员以及成员方法的访问特点
package com.atguigu.i_duotai;
public class Fu {
int num = 100;
public void method(){
System.out.println("父类中的method方法");
}
}
package com.atguigu.i_duotai;
public class Zi extends Fu{
int num = 10;
public void method(){
System.out.println("子类中的method方法");
}
}
package com.atguigu.i_duotai;
/****/
public class Test {
public static void main(String[] args) {
//多态方式new一个对象
Fu fu = new Zi();
//成员变量没有多态性,成员方法要是有重名的直接子类重写就行了
System.out.println(fu.num);//父类的100
fu.method();
System.out.println("============");
//原始方式
Zi zi = new Zi();
System.out.println(zi.num);//子类的10
zi.method();
}
}
输出:
100
子类中的method方法
============
10
子类中的method方法
3)多态的好处
4)多态的转型
package com.atguigu.k_duotai;
public class Test01 {
public static void main(String[] args) {
Dog dog = new Dog();
method(dog);
Cat cat = new Cat();
method(cat);
}
public static void method(Animal animal) {//Animal animal = Dog Animal animal = Cat
if (animal instanceof Dog){
animal.eat();
//向下转型
Dog dog = (Dog) animal;//强制从dog类转为animal
dog.lookDoor();//就可以调子类成员方法了
}
/***
* 向下转型容易出现的问题: classCastException----->类型转换异常
*
* 出现问题的原因: 转型的时候,等号左右两边型号不一致
*
* 解决方案:做判断
* 关键字:instanceof关键字------>用来判断某个对象是否属于某种数据类型。 返回值为布尔类型
* 格式:
* 对象名 instanceof 类型--》关键字前面的类型是否属于关键字后面的类型
*
* */
if (animal instanceof Cat){
animal.eat();
Cat cat = (Cat) animal;
cat.catchMouse();
}
}
}
多态练习
2)分析
3)代码实现
package com.atguigu.l_duotai;
/**
* -USB接口类,包括开启功能、关闭功能
* **/
public interface USB {
void open();//不写abstract也可以
void close();
}
package com.atguigu.l_duotai;
public class KeyBoard implements USB{
//重写接口方法
@Override
public void open() {
System.out.println("键盘开启");
}
@Override
public void close() {
System.out.println("键盘关闭");
}
}
package com.atguigu.l_duotai;
/**Mouse类**/
public class Mouse implements USB{
@Override
public void open() {//重写接口方法
System.out.println("鼠标开启");
}
@Override
public void close() {
System.out.println("鼠标关闭");
}
}
package com.atguigu.l_duotai;
public class NoteBook {
public void start(){//成员方法
System.out.println("开机了");
}
/**
* 接收TEST类传过来的Mouse对象
*USB接收
* USB是mouse的接口类型 USB usb = mouse
* mouse是usb的接口实现类对象
* 接口看成父类。接口实现类看成子类
* 多态的体现
* **/
public void useUSB(USB usb){
// USB usb = keyBoard
usb.open();//多态调用
usb.close();
}
public void stop(){
System.out.println("关机了");
}
}
package com.atguigu.l_duotai;
/**
* 定义笔记本类,具备开机,关机和使用USB设备的功能,具体是什么USB设备,笔记本不关心,
* 只要符合USB规格的设备都可以。鼠标和键盘要想在电脑上使用,
* 那么鼠标和键盘也必须遵守USB规范,不然鼠标和键盘的生产出来无法使用
* 描述笔记本类,实现笔记本使用USB鼠标、USB键盘
*
* -USB接口,包括开启功能、关闭功能
* -笔记本类,包含运行功能、关机功能、使用USB功能
* -鼠标类,要符合USB
* -键盘类,要符合USB接口
*
* **/
public class Test01 {
public static void main(String[] args) {
NoteBook noteBook = new NoteBook();
noteBook.start();//笔记本类调用笔记本类的成员方法开机
Mouse mouse = new Mouse();
noteBook.useUSB(mouse);//传了一个mouse对象给接口实现类Mouse
System.out.println("==================");
KeyBoard keyBoard = new KeyBoard();
noteBook.useUSB(keyBoard);
noteBook.stop();
}
}
object类
1)使用object接收所有类
class Person {}
class Student {}
public class Test {
public static void main(String[] args) {
Object per = new Person();
Object stu = new Student();
}
}
2)object类的结构图
下面我们一个个方法进行分析,看这些方法到底有什么作用: 1. clone() 保护方法,实现对象的浅复制,只有实现了Cloneable 接口才可以调用该方法,否则抛出 CloneNotSupportedException 异常。 2. getClass() final方法,返回 Class 类型的对象,反射来获取对象。 3. toString() 该方法用得比较多,一般子类都有覆盖,来获取对象的信息。 4. finalize() 该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用。 5. equals() 比较对象的内容是否相等 6. hashCode() 该方法用于哈希查找,重写了equals 方法一般都要重写 hashCode 方法。这个方法在一些具有哈希功能 的 Collection 中用到。 7. wait() wait方法就是使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。 wait() 方法一直等待,直到获得锁或者被中断。 wait(long timeout) 设定一个超时间隔,如果在规定时间 内没有获得锁就返回。 调用该方法后当前线程进入睡眠状态,直到以下事件发生。 其他线程调用了该对象的notify 方法。 其他线程调用了该对象的notifyAll 方法。 其他线程调用了interrupt 中断该线程。 时间间隔到了。 此时该线程就可以被调度了, 如果是被中断的话就抛出一个InterruptedException异常。 8. notify() 该方法唤醒在该对象上等待的某个线程。 9. notifyAll() 该方法唤醒在该对象上等待的所有线程。
3)object类的常用方法
(1)toString方法
toString() :取得对象信息,返回该对象的字符串表示 我们先看一个简单的例子:class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Test {
public static void main(String[] args) {
Person per = new Person("Mr.Q", 20);
System.out.println(per);
}
}
输出:
iqqcode.algorithm.bintree.Person@1ee12a7
在使用对象直接输出的时候,默认输出的是一个对象在堆内存上的地址值;如若要输出该对象的内容,则要覆写
toString()
方法
覆写Person中的 toString() 方法 如下
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "名字为:" + this.name + ",年龄为:" + this.age;
}
}
public class Test {
public static void main(String[] args) {
Person per = new Person("Mr.Q", 20);
System.out.println(per);
}
}
package com.atguigu.b_object;
import java.util.ArrayList;
public class Test01 {
public static void main(String[] args) {
Person p1 = new Person("柳岩",36);
Person p2 = new Person("涛哥",18);
System.out.println(p1);
System.out.println(p2);
System.out.println(p1.toString());//com.atguigu.b_object.Person@135fbaa4
System.out.println(p2.toString());//com.atguigu.b_object.Person@45ee12a7
ArrayList<String> list = new ArrayList<>();
list.add("abc");
list.add("def");
System.out.println(list);// [abc, def]
}
}
(2)equals方法
package com.atguigu.b_object;
public class Test02 {
public static void main(String[] args) {
// 创建两个Person对象,内容相同
Person p1 = new Person("柳岩",36);
Person p2 = new Person("柳岩",36);
// 使用equals方法比较p1和p2,期望结果是false
//System.out.println(p1.equals(p2));//false
// 使用equals方法比较p1和ArrayList对象,期望结果是false
//ArrayList<String> list = new ArrayList<>();
//System.out.println(p1.equals(list));
// 使用equals方法比较p1和null,期望结果是false
//System.out.println(p1.equals(null));
// 使用equals方法比较p1和自身,期望结果是true
System.out.println(p1.equals(p1));
System.out.println("=========================");
// 创建两个String对象,内容相同
String s1 = new String("abc");
String s2 = new String("abc");
// 使用equals方法比较s1和s2,期望结果是true
System.out.println(s1.equals(s2));//true
//equals重写 String方法内容 所以结果是true 但在实际内存中,内存的地址不一样
// 使用==比较s1和s2,期望结果是false
System.out.println(s1==s2);//false
}
}
/**
*
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 重写equals方法,通过name和age来判断两个Person对象是否相等
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
Person person = (Person) obj;
return age == person.age && name.equals(person.name);
}
}
*
*
* **/
@Override
public boolean equals(Object obj) {
// 判断是否为同一对象
if (this == obj) {
return true;
}
// 判断传入的对象是否为空或者是否属于要比较的类对象
if (obj == null || getClass() != obj.getClass()) {
return false;
}
// 向下转型,将 Object 类还原为 Person 类
Person person = (Person) obj;
// 比较 name 和 age 是否相等
return age == person.age && Objects.equals(name, person.name);
}
比较结果为 true 所以,引用类型的数据在进行比较时,应该先覆写 equals() 方法,不然比较的还是两个对象的堆内存地址值,必然不会相等.
(4)getclass方法和native方法
getclass方法
public class Person {
private String name;
private int age;
// 默认构造函数
public Person() {
}
// 带参数的构造函数
public Person(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;
}
// 重写toString方法
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
native方法