1Java类的基本结构
1.1类和对象
1.1.1面向对象和面向过程
1.1.2什么是对象
- 定义:对象是客观存在的事物,可以说任何客观存在的都是可以成为对象
- 万事万物皆对象
- 但是Java中存在基本数据类型,所以没有完全实现面向对象编程
- 对象依赖于类存在(模板-个体实例)
- 分析过程是先有对象后有类,而开发过程是先有类在再有对象
- 开发过程使用的是对象
1.1.3什么是类
- 定义:类是描述对象的“基本原型”,定义一种对象所能拥有的数据和能完成的操作
- 类是对象中所拥有的数据(属性)和能完成的操作(方法)
- 类是程序的基本单元
1.2类和对象的声明
1.2.1类的格式
【访问权限修饰符】【修饰符】 class 类名{
成员列表
}
eg: public static class DemoA{
}
- 类名符合Java标识符的结构要求,一样的命名规则:首字母大写,多个单词则每个单词首字大写。如GetClass,Money
- 【访问权限修饰符】:public,protect,private,(default不写)
- 【修饰符】final,abstract,native等
1.2.2成员属性:
声明变量的格式:
【变量修饰字】变量数据类型 变量名1,变量名2 【=变量初值】;
eg:private String str = "123"
- 变量数据类型可以是任意数据类型(基本数据类型/类/接口/数组等)
1.2.3创建对象
创建对象格式(这个过程也叫做实例化):
类名 引用名 = new 类名()
// 声明 初始化(调用了类的一个构造方法)
创建对象的步骤是:
- 说明新建对象所属的类名
- 说明新建对象的名字
- 用new为新建对象开辟内存空间
1.2.4调用成员属性
在实例化类的对象后,可以使用成员运算符(.)来访问类中的成员,格式:
对象名.成员名
eg: Teacher.age = 15;
1.2.5方法的声明格式
- 方法是一个对象的行为,能够接受什么样的消息。
- void无返回值,方法修饰可以不写
基本声明格式:
【访问控制】【方法修饰】 返回类型 方法名称(参数1,参数2...){
方法体:
}
eg: public static void DemoA(String s1,Stirng s2){
}
1.2.6方法的调用
不管是什么权限修饰符,在同类中的方法调用其他方法直接使用方法名就可以。除了static修饰另行讨论。
1.2.7可变参数
- 定义:可以根据占位符的个数提供不同的数据变量以供输出
- 适用于参数个数不确定,类型确定的
ddddddddddddddddddddddddddddddddddddddd
1.2.8数组作为参数练习:
可以使用 int [] array,也可以使用 int … array写法;
定义一个方法,参数是数组[可变参数],在方法中,对数组元素进行排序;
定义测试类和方法,在测试方法中输出排序结果.
1.2.9方法参数小结:
我们发现如上的两个方法定义,方法swap方法参数是基本类型,在方法内部的a,b发生了改变,但是调用处的代码是不发生改变的,传递的是值;
第二个方法 swap2参数是一个数组,方法中对数组元素进行了修改,调用处的数组的值也发生了改变,传递的是值;但是这个值比较特殊,相当于调用处的数组引用,和方法处的数组引用是指向堆中的同一个区域.
1.2.10递归调用:
ddddddddddd ddddddd
1.2.11学习习惯和方法:
1.2.12方法的重载(❤)
- 定义:同一个类中多个方法可以享有相同的方法名,且参数类型列表必须不同、参数个数不同或者参数类型不同、参数的排列顺序不同
过程:定义一个方法名toString(),接收不同的参数,编译器会根据传递的实际参数自动判断具体调用哪个重载方法。
优点:不用定义很多的方法名,可读性更好了;
dddddddddddddddddddd
同一个类Pig中,两个[多个]方法名 eat 相同,参数个数不同: eat() 0个参数 eat(String food) 一个参数 ;
1.3构造方法:
- 定义:在创建对象的同时,完成新建对象的初始化工作
- 在实例化对象的同时会自动调用构造方法
- 用来给数据成员分配资源或初始化数据成员
1.3.1构造方法的特点:
- 与类同名的方法
- 没有返回值,也不能写void
- 主要是完成新建对象的初始化工作
- 不能显示直接调用,而是用new来调用,或者this/super
- 在创建一个类的新对象的同时,系统自动调用该类的构造函数,为新建对象的初始化
1.3.2默认的构造方法:
默认情况下:
Java类必须要有构造方法来构建对象 ->
没有编写的话Java会自动的为该类提供一个默认的构造方法,该方法为:
- 是无参构造
- 空方法体,不执行任何初始化操作
默认情况下:
1.3.3语法要求:
声明格式:
【访问权限修饰符】类名(参数列表){
方法体
}
可以注意到,构造方法是没有返回类型的!
1.3.4构造的调用:
类名 引用变量名 = new 类的构造函数(构造方法参数列表);
eg1: Person p = new Person();
eg2: Person p = new Person(a,b);
1.3.5构造方法重载:
1.3.6带参数构造的意义:
1.3.7带参数构造练习 :
定义一个员工类,员工编号,姓名,部门,工资,部门经理,我们要求使用构造方法给属性进行赋值;
定义一个方法,输出员工的详细信息;
定义一个测试类,测试类创建员工对象同时对属性进行赋值,调用方法做输出.
对于构造而言,如果定义了一个带参数的构造方法,那么默认的无参数的构造将会被覆盖,也就是无参数的构造不存在了;没法再使用 new 类名();
所以通常情况下,我们再创建一个类,定义带参数的构造的时候,还会将默认的无参数的构造也显式定义出来。
1.3.8This的使用:
This表示的是当前类的对象。
1.3.9代码演示:
图书代码:
package day10;
/**
- 图书类
- @author Administrator
*/
public class Book {
String isbn; //9787540489304
String name;//断舍离
String publish;//出版社: 湖南文艺出版社
double price; //闪 购 价 ¥37.30
/**
* 通过构造给属性赋值
* @param isbn
* @param name
* @param publish
* @param price
*/
public Book(String isbn, String name, String publish, double price) {
this.isbn = isbn;
this.name = name;
this.publish = publish;
this.price = price;
}
/**
* toString方法
*/
public String toString() {
return "Book [isbn=" + isbn + ", name=" + name + ", publish=" + publish + ", price=" + price + "]";
}
}
测试类:
package day10;
/**
- 测试类
- @author Administrator
*/
public class TestBook {
public static void main(String[] args) {
//构造对象
Book book = new Book("9787540489304","断舍离"," 湖南文艺出版社",37.30);
//调用toString方法
String info = book.toString();
//输出结果
System.out.println(info);
System.out.println("*****************");
System.out.println(book.toString());
System.out.println("*****************");
System.out.println(book);
}
}
2 Java深入面向对象
2.1面向对象特性
2.1.1三大特征说明:
-
封装:
客观事物封装成抽象的类,可以对自己的数据和方法进行信息隐藏,也就是在对象内部某些数据(方法/属性)是可以私有的,通过一个受保护的接口访问其他对象。 -
继承:
1.新类(派生类、子类)从现有的类(基类、父类)中派生,称为类继承,子类继承了原始类的特性。
2.继承是一种联结类的层次模型
3.子类可以从父类继承方法和实例变量,并且子类还能额外修改增加方法以便适合实际需要。 -
多态:
1.是指允许不同类的对象对同一消息作出响应
2.多态语言有灵活、抽象、行为共享、代码共享的优势
2.1.2包定义和导入
- 为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间
- 包的作用:
1.把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用
2.如同文件夹一样,包也采用了树形目录的存储方式,包可以避免名字冲突。
3.包也提供了限定了访问权限的一个控制范围,拥有包访问权限的类才能访问某个包中的类
4.包的命名要全部小写,以互联网域名颠倒形式作为包名。
例如:baidu.com,所有的包名要以com.baidu开始。
个人项目的包名:com.ccp.shop.menu
//com.个人.项目名.功能模块名
2.1.3类访问修饰符:
Public:任何位置
Default: package 包级别,即同一个包下可以访问.
2.1.4成员访问修饰符
- 总共有四种
Public:同类,同包,不同包的子类,不同包的非子类
protected:同类,同包,不同包的子类
Default: 同类,同包
private:当前类
2.2封装
2.2.1概念:
- 封装是将对象的信息隐藏在对象内部,禁止外部程序直接访问对象内部的属性和方法
1.每个属性都可以生成对应的两个方法setter/getter;
2.Setter用来赋值,Getter是用来取值的。 - 实现步骤:
1.修改属性的可见性,限制访问权限
2.设置属性的读取方法
3.在读取属性的方法中,添加对属性读取的限制
2.2.2实现代码:
在这里插入代码片
package day008;
/**
- 对信息封装"; 1.属性私有化,外部不能直接访问,但是为了我们的程序运行,用2步 2.提供”公共“的方法来访问私有的属性。
- 3.可以在方法中加入一些判断
- @author admin
/
public class Person {
// 表示这个name是私有化
private String name;
private int age;
/*
* 提供公共的方法来访问私有属性: 给属性进行赋值
*
* @param name
/
public void setName(String name) {
if(name == null)
{
name =“默认值”;
}
this.name = name;
}
/*
* 公共方法的功能是访问私有的属性,获取私有属性的值并返回
*
* @return
*/
public String getName() {
return this.name;
}
}
package day008;
public class TestPerson {
public static void main(String[] args) {
Person p = new Person();
p.setName(null);
System.out.println(p.getName());
}
}
2.2.3练习:
创建一个班级类,班级类中的属性分别为编号,名称,简介;
使用封装的思想,为这个类属性提供公共的访问方法;
创建测试类,创建班级类对象,对属性进行赋值,输出属性的信息。
toString ?自己决定
2.3继承
2.3.1引入:
- 引入继承,实现了代码重用
- 引入继承,实现了递增式的程序设计
- 能减少代码和数据的重复冗余度,并通过增强一致性来减少模块间的接口和界面,从而增强了程序的可维护性
- 能清晰地体现出类与类之间的层次结构关系
2.3.2规约:
- 如果有两个类A 类B,满足 A[Dog] 是B[Animal] 的关系,我们就可以说 A 继承了 B,或者A 扩展 B,
1.使用关键字extends 来表示继承关系 A extends B
2.我们称A 类为子类[派生类]; B为父类[超类 基类]
3.Java中类 只支持单继承; 一个类,只能有一个直接的父类
4.子类会继承父类中公共成员[公共属性;公共的方法]; 在子类对象中,就可以直接使用父类中的公共属性和方法.
5.创建子类对象,默认会调用父类的无参数的构造,而且,父类的无参数的构造,先于子类的构造执行。
6.如果父类中包含一个带参数构造,那么无参数构造没有显式声明的话,那么父类就不存在无参数构造;此时子类如果想调用父类的带参数的构造,就要在子类的构造中使用
Super(参数);而且,这个super语句必须出现在子类构造的第一行
2.3.3继承语法:
格式:
【访问权限修饰符】【修饰符】子类名 extends 父类名{子类体}
- Java是单亲继承,extends关键次后只能有一个父类名,不能出现列表(多个父类);但是接口可以
2.3.4继承练习:
创建一个老师类[父类];老师类老师名字;包含了一个上课的方法;
Java老师[子类]继承老师;
C#老师[子类]继承老师;
创建测试类,实例化Java老师对象;C#老师对象,调用父类老师的方法.
2.3.5子类构造调用父类:
2.3.6子类显式调用父类构造:
2.3.7Super关键字
super关键字:
super关键字用在子类中;
可以用在子类的构造方法中;调用父类的构造方法 super();
放在子类的普通方法中,可以调用父类的公共的方法: super.父类方法名();
2.3.8方法的重写:
- 定义:子类中的方法依然和父类方法的声明形式一样,但是具体方法体却不同,这种做法就叫做方法覆盖。
注意点:
1.覆盖的两个方法的方法名、参数列表必须完全一致(子类重写父类的方法);返回值:①是基本数据类型,则应该保持一致。②是类,子类的覆盖方法返回值必须是父类返回值或者其子类(协变返回类型)
2.子类抛出异常 < = 父类
3.子类方法访问级别 > = 父类
2.3.9引用和对象:
2.3.10多层继承:
2.3.11再说继承:
package com.exts;
public class Animal {
String name="animal~";
String type="animal type~!";
public void t() {
System.out.println("animal的普通方法");
}
public void t2() {
System.out.println("animal的普通方法t2");
}
}
package com.exts;
public class Pig extends Animal{
String color;
String name=“Pig~”;
@Override
public void t() {
System.out.println(“Pig 普通方法 t方法,@override”);
}
public void t3() {
System.out.println(“Pig的普通方法T3”);
}
}
package com.exts;
public class TestAnimal {
public static void main(String[] args) {
// Animal类引用 指向是 Animal的对象
// 引用 = new 类型();
//父类引用 指向 父类对象
//通过引用调用的属性和方法都是和父类相关的.
Animal animal = new Animal();
System.out.println(animal.name);
animal.t();
System.out.println("*****************");
//子类引用 指向 子类对象
//此时子类中定义了name t() 所以调用此时都是子类的属性和方法
//子类有,就调用子类的
Pig p = new Pig();
System.out.println(p.name);
p.t();
//"子类没有",在访问修饰符允许的范围(能引用到),就调用父类的属性
System.out.println(p.type);
p.t2();//调用父类的方法
System.out.println("*****************");
//父类引用 指向 子类对象(向上转型)
Animal apig = new Pig();
//此时属性的值,都是"父类"中属性定义的值(不管子类中是否有同名的属性);
System.out.println(apig.name);
System.out.println(apig.type);
//方法
//Pig 普通方法 t方法,@override
//由于子类中队t方法进行了重写,所以此时调用的是子类中的方法
apig.t();
//父类有,子类没有重写 ;这个t2只有在父类中有定义,只能是父类的方法
apig.t2();
System.out.println("*****************");
//子类 引用 指向 父类对象(这种情况下,不可行)
// java.lang.ClassCastException:
//com.exts.Animal cannot be cast to com.exts.Pig
//不能直接"硬转"
Pig pAnimal = (Pig)new Animal();
}
}
2.4多态
2.4.1定义:
- Java中多态性指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式
- 发送消息就是方法调用
比方说按下 F1 键这个动作,如果当前在IE界面下弹出的浏览器的帮助文档;如果当前在 Word 下弹出的就是 office帮助;在 Windows 下弹出的就是 Windows 帮助和支持,可见,同一个事件发生在不同的对象上会产生不同的结果 - 多态的主要作用适用于消除类型之间的耦合关系。
2.4.2分类:
编译时多态:主要是方法的重载,通过参数列表的不同来区分不同的方法。
在程序编译期间
根据参数列表不同,来决定最终绑定哪个方法进行调用的操作也称为重载;编译器完成判断。
运行时多态【继承和接口】:也叫作动态绑定,一般是指在执行期间(非编译期间)判断引用对象的实际类型,根据实际类型判断并调用相应的属性和方法。主要用于继承父类和实现接口时,父类引用指向子类对象。
2.4.3编译时多态
同一个对象,方法名相同,参数不同,执行过程和结果也不同。
2.4.4继承实现多态(运行时)
运行时多态: 程序再运行期才确定,要执行那个对象的方法,称为运行时多态。
继承
重写覆盖
对象向上造型-父类引用指向子类对象
操作步骤:
1.创建父类,定义方法:
2.创建子类重写父类的方法:
3.场景类中,有一个方法,父类引用作为参数:
4.实际调用的时候传递的参数为子类对象
上面的案例,我们发现,方法名就叫show,但是不同的对象:
New Tiger()->=执行就是tiger的方法;
New Lion() -> 执行这个方法就是调用 lion的方法;
而lion和tiger的方法执行过程和结果是不同的。
相同的方法,对于不同对象来调用,执行过程和结果是不同的。这称为多态。
1.4.5课堂练习:
2选1
上面的案例,自己去实践一下。
去自定义一个应用场景,使用的操作步骤和我们上面的步骤一致;
1.5抽象类和抽象方法:
抽象类与抽象方法.
在面向对象的概念中,知道所有的对象都是通过类来描绘的,但是反过来却不是这样。并不是所有的类都是用来描绘对象的,如形状类是抽象的类,圆、三角形等是具体类
用abstract修饰的类就是抽象类。
抽象类是抽象方法的容器,如果某个类中包含有抽象方法,那么该类就必须定义成抽象类。抽象类中也可以包含有非抽象的方法甚至抽象类中可以没有抽象方法(只要一个类不应该有具体对象,就应该是抽象类,不一定是有抽象方法的)
1.抽象类可以包含普通方法吗? 可以的
2.抽象类中可以包含抽象方法吗? 是
3.抽象类的普通方法能否被子类继承? 能
4.抽象类中可否有显式的构造方法? 有,依然遵循继承关系
5.一个类继承了抽象类,能否不实现抽象类的抽象方法? 可以,但是要继续抽象
6.抽象类中可以包含属性吗? 可以的
7.使用场景主要是一些抽象概念性内容定义: 形状,门 ;主要用来做模板,标准;也就是定义了一个方法的签名,具体实现留给子类;
1.5.1步骤:
1.5.2要求:
创建一个抽象形状类,里面有两个抽象方法,计算面积,计算周长。
创建两个子类,分别为圆形和正方形,在子类中实现[重写]父类抽象方法。
测试类,创建子类对象,调用方法输出结果
2.6修饰符:final
2.6.1常量:
2.6.2方法:
如果用来修饰一个方法,表示这个方法不能被重写。
2.6.3类:
final来修饰一个类,表示这个类不能被继承。
例如: java.lang.String就是final类;大家可以找找其他的final类.
2.7修饰符static:
- 针对一个类所有对象的共性属性, Java采用static成员完成统一调用
- static在变量或方法之前,表明它们是属于类的,称为类方法(静态方法)或类变量(静态变量)。若无static修饰,则是实例方法和实例变量
- 和类的其他成员属性不同, static成员并不存放在对象对应的堆空间中,通过对JVM的分析发现,其会将static成员存放在方法区中,每个对象的相应static共享同一段内存
2.7.1修饰类:
2.7.2修饰方法:
2.7.3修饰属性:
2.7.4Static import:
2.8接口:
2.8.1引入:
实现多继承;
设计,标准制定。
2.8.2定义语法:
成员变量方面,在接口中只存在公开静态常量(即便没有使用static final修饰,Java也会默认确定其性质)
成员方法方面,在接口中只存在公开抽象方法(即便没有abstract修饰,Java也会默认其抽象性质)
规约:
一个类可以实现多个接口:
Class 类名 implements 接口1,接口2,接口3 …
类中要实现接口中的抽象方法。
或者不实现的话,这个类就要定义为抽象类.
package com.inters;
/**
- 接口不能直接进行实例化
- @author Administrator
*/
public interface IFly {
void fly();
}
package com.inters;
public interface IEat {
void eat();
}
package com.inters;
/**
- implements 实现 @Override重写接口的方法
- @author Administrator
*/
public class Bird implements IFly, IEat {
@Override
public void fly() {
System.out.println("笨鸟在飞");
}
// alt+/
@Override
public void eat() {
System.out.println("笨鸟在吃虫子");
}
}
package com.inters;
public class TestBird {
public static void main(String[] args) {
Bird bird = new Bird();
bird.eat();
bird.fly();
IFly bird2 = new Bird();
bird2.fly();
}
}
一个接口能继承一个接口吗?
一个接口可以继承多个接口吗?
如果一个类,继承了类同时有实现了接口,语法是什么样子的?
2.8.3接口和抽象类区别:
2.8.4类实现接口:
2.8.5接口应用[多态]:
2.9枚举:
2.10关联和依赖:
•两个类之间的简单关联表示了两个同等地位类之间的结构关系。当你想要表示结构化关系时使用关联
•关联表示has-a关系,如学生拥有一个课程,往往表现为B作为A的属性存在(A关联B)
•最典型的一对一关系莫过于人和证件之间的关联,例如:一个人只能有一个驾照,而一个驾照只能归属与一个人:
•人还可以跟其他事物构建一对多的关联关系,比如将驾照换为荣誉证书,那么一个人可以有多个荣誉证书,我们可以使用数组或集合来描述这个关系:
•依赖关系是一种使用关系,特定事物的改变有可能会影响到使用该事物的事物,反之不成立
•此关系最为简单,也最好理解,所谓依赖就是某个对象的功能依赖于另外的某个对象,而被依赖的对象只是作为一种工具在使用,而并不持有对它的引用
•依赖体现了“ use a”关系
•依赖关系一般使用方法的参数体系
•一个人自创生就需要不停的呼吸,而人的呼吸功能之所以能维持生命就在于吸进来的气体发挥了作用,所以说空气只不过是人类的一个工具,而人并不持有对它的引用。
2.112-28回顾:
1.继承: 类A is 类B,那么我们就说A继承了B;使用extends来表示,继承,也称为扩展;A称为子类,将B称为父类。A称为派生类,B称为基类,超类。
2.子类可以继承父类公共成员,公共的属性和方法。
3.除了子类可以继承父类的成员以外,我们子类可以自己扩展;子类可以重写父类的方法,也可以有自己的方法;可以继承父类公共的属性,也可以有自己的属性。
4.重写:覆写,覆盖。子类中对父类的方法进行重新的定义;但是要求子类的方法修饰符返回值类型方法名,参数列表和父类一致; 如果返回值为引用类型,那么子类返回值的类型是父类方法返回值的子类也可以; 子类方法的修饰符不能小于父类方法访问修饰符。
5.多态: 允许不同类的对象对同一消息做出相应; 同一方法,对于不同的对象来说,执行过程和方法不同;
吃: 人:[大人 小孩 猪 ]
6.继承来完成多态的方式:
创建父类;创建父类的方法;创建子类,重写父类的方法;父类引用作为参数;传递子类对象给方法;
Eg:昨天的作业:
7.父类引用指向子类对象:
8.抽象类和抽象方法;
9.修饰符final: final class不能被继承;final 属性是常量;final方法 不能被重写。
10.访问修饰符: private default protected public . 口述