类语法结构分析
[]表示可选部分
package 包名;
[修饰符]class 类名
[extends 父类] [implements 接口1, 接口2 ,....]
{ //类体
[属性]
[构造方法 初始化属性]
[方法]
}
1. 属性 Field 域 对象中保存数据的区域
Attribute属性
语法:
[修饰符] 数据类型 属性名[=初始值];
规律:对象创建,开辟空间,属性有默认值
String name="Tom";
String类型默认null
int类型默认0
数值类型 0或者0.0
字符类型 char '\u0000'
布尔类型 boolean false
引用类型 ref null reference引用
2. 方法 method
语法
[修饰符] 返回值类型 方法名(参数表)
[throws 声明抛出的异常]
{ //方法体
返回值类型是void 无需返回任何结果
可以通过return;语句 提前结束方法调用
返回值类型不是void,必须写return XXX; XXX可以为变量、常量、表达式、方法调用
}
方法的重载 overload
定义 一般在一个类中
方法名相同参数表不同 (类型、数量、顺序)
注意:返回值类型是否相同不作为重载的依据
用途:便于用户使用 只需记忆少数的方法名 通过传入不同的参数 来区分不同方法
通过传入不同的参数,来区分不同方法
举例:打印方法就设计为重载方法
System.out.print(123);
System.out.print(1.0);
System.out.print('A');
System.out.print("测试");
class Person{
public void eat 吃饭(饭 f){
...
}
public void eat 吃面(面 m){
...
}
public void eat 吃药(药 y, 水s){
...
}
}
return后面不可以有打印语句
报错信息:unreachable code
返回之后在打印没有意义 Java不打印没有意义的语句
在return前面加打印语句跟踪代码是否被执行
Duplicate method add(int,int) int type
重复的、二义性
3. 构造方法 Constructor
也称为 构造方法 构造函数 构造器 构造子 构造
3.1 无参构造
class Animal(){
String name;
public Animal(){
}
}
要点:
1. 使用类名作为方法名
2. 没有返回值类型 连void都不能有
3. 用途:初始化属性
4. 调用时机:伴随着对象的创建而调用
new Animal(); 调用无参构造方法
分析一下两行代码执行步骤细节:
Animal a3=new Animal("小兔儿",1);
a3.eat("鸡蛋");
1> JVM第一次认识某个类:类加载过程 加载某个类
JVM虚拟机先加载Animal.class类。将类的信息读入code区Animal。作为对象的模板,可以创建对象
2> Animal a3在栈区分配变量a3
3> new对象在heap堆区分配空间,创建对象
属性提供默认值:name null age 0
4> 构造方法伴随对象创建而调用,执行有参构造
初始化属性: name "兔儿" age 1
5> 对象地址赋值给a3
6> 平时说 调用a3对象的eat方法
严格说 针对a3指向对象调用code区中Animal类的eat方法 ,参数"鸡蛋"
5. 构造方法也可以重载 方法名相同,参数表不同
有参构造
public Animal(String name,int age){ //局部变量
// this关键字 表示当前对象 区分同名的成员变量 和局部变量
this.name=name;
this.age=age;
System.out.println("有参构造,Animal(String,int)");
}
Scanner sc=new Scanner(System.in);
调用有参的构造方法,参数system.in
扫描器有个属性:系统标准输入流
无参构造 有参构造构成重载
6. 系统会为每个类提供公开的、无参的、空实现的默认的构造方法
public Animal(){
一旦我们自定义构造方法,默认的就会被替代掉,消失
要求:也自定义午餐构造方法,避免丢失
}
有参构造,初始化所有属性
7. this关键字 表示当前对象 当前正在运行的对象
this.成员 成员包括属性、方法
主要用于this.属性
目的:区分同名成员变量和局部变量
this.name=name;
8. this(); 表示调用本类的其他的构造方法
可以传参
目的:复用其他构造方法的代码
构造方法只能在构造方法的第一行调用
9. 面向对象编程,使用类创建对象 提供属性 调用方法。属性代表数据 方法代表行为
面向对象和面向过程的区别
软件=程序+文档
程序=数据结构+算法
面向对象:先考虑数据结构再考虑算法
面向过程:先考虑算法再考虑数据结构
找到合适的类,创建对象,提供数据属性,调用方法,得到结果
找Caipiao类 cp1 25 5 create ds1
10. 类 对象的特点
可复用的
对象功能尽可能单一 各司其职 各尽所能
软件工程理念:高内聚 低耦合
高内聚:每个对象功能完备 自给自足
11. 面向对象的关键:抽象
将同类的对象进行抽象,形成一个类 class
对象-泛化 找出共性
业务抽象 属性
业务抽象 方法
12. 方法的重载 overload
方法名相同 参数表不同 类型 数量 顺序
返回值类型是否相同不作为重载的依据
好处:便于用户的使用 只需要记忆少量的方法名,通过不同参数区分调用不同方法
13. 构造方法
使用类名作为方法名
没有返回值类型
用途:初始化属性
调用时机:伴随对象创建而调用
构造方法可以重载
系统会为每个类都提供默认的构造方法 公开的 无参的 空实现的 如果自定义构造方法,默认的就会消失
建议先写无参的
14. this关键字:当前对象
this.属性 用于区分同名的成员变量和局部变量
this();表示调用本类其他构造方法 可以传参数
只能在构造方法的第一行使用
String s1 = Arrays.toString(ds1);
将ds1数据生成如下的String对象返回
[1,3,5,...,6,9]
能清楚的看到数组的每个元素
15. 面向对象的三大特征(基石):封装 继承 多态
一、封装:Encapsulation
含义:类中的成员,该公开的公开,该隐藏的隐藏
方法都公开了,属性隐藏了,通过方法可以间接使用隐藏的方法。getName setName
类体:属性 方法 构造方法
封装能够让操作的数据和功能更加方便 安全
访问控制修饰符:
public protected default private
公开的 受保护的 默认不写 私有的
本类 本类 本类 本类
同包 同包 同包 X
子类 子类 X X
其他 X X X
可见范围递减
修饰符 作用范围 本类 同包 子类 其他
public OK OK OK OK
protected OK OK OK
default OK OK
private OK
1. 属性封装
(1) 属性私有 private修饰
private int id; 保证数据安全
private String name; 保证数据安全
(2) 提供一组方法 读/写属性
getters / setters
在类中属性为private 但其他类中的方法想查看属性,提供下面的方法。也就是对属性的一种访问:外界不能随意访问属性,想用可以,绕一下,通过方法来用,相对安全。
不提供方法,私有属性外界看不到,不可以用。想用需要用getXxx setXxx 其中xx为属性名称,首字母大写
一句话 属性私有,get set方法
具备可读属性 name 方法名 getXxx
public String getName() {
return name;
}
具备可写属性 name 方法名 setXxx
public void setName(String name){
this.name=name;
}
方法名 返回值类型 参数表 三要素
getXxx 无参 需要返回结果
setXxx 有参 不需要返回结果
位置:写在构造方法的后面,业务方法的前面
注意:Boolean类型属性 setXxx写法不变 getXxx应该改为isXxx
2. 方法封装
区分不同修饰符特点
public 公开的 任何地方都可以访问
protected 受保护的 主要供子类使用
private 私有的 只有本类可以使用
public修饰:算工作量,会增加后期维护成本
private修饰:作为辅助方法,后期维护成本较低
3. 构造方法封装
一般构造方法使用public修饰,作用
public Student(){}
其中类中可以new Student(); 间接调用无参构造
用途:一种设计模式--单例模式
保证一个类在系统中最多创建一个对象(实例)
好处:减少大量对象的创建,减少内存垃圾,降低GC的启动频率,由于GC的启动对系统性能影响较大,所有单例模式可以提高系统性能
4. 继承 Inheritance
含义:继承是软件复用的一种形式
当两个类存在逻辑上的"is a"关系时,使用继承复用但不是所有的软件复用都用继承
继承是多态的前提,没有继承就没有多态
猫狗鱼虫是对不同对象的抽象的泛化
Animal是对猫狗鱼虫再抽象泛化
猫狗鱼虫 ->Animal 泛化
Animal -> 猫狗鱼虫 派生
继承语法
使用关键字extends
class Super{
// 父类 超类 Super是Sub的父类
}
// Sub is-a Super
class Sub extends Super{
// 子类
}
类图
表示类的信息,以及类间的关系
注意:代码的层次结构,类体,方法体区分
每个类相对独立 不能嵌套
Student s1 = new Student(2, "Tom", 23, true);
类 对象名称 = new 无参/有参构造方法(属性)
(2)Java只能允许类的单继承
一个类最多只能有一个父类
C++允许的,Java不允许,好处:关系的简单性
(3)Object类是所有类的共同父类(根基类)
java.lang.Object
任何类都直接或者间接继承自Object类
都具备Object的特征 Everything is Object
(4)子类能够从父类继承到能继承的资源
前提使用public protected修饰的属性 或 方法
注意:构造方法不能继承 没有意义(类名作为方法名)
(5)创建子类对象,会先创建父类对象
调用子类构造方法,先递归的调用父类的构造方法
递归调用
原理:Java规定任何构造方法的第一行默认就是super();表示调用父类无参的构造方法
无参构造的super();是默认不显示的
this关键字 表示当前对象
this.属性 用于区分同名的成员变量和局部变量
this.(); 表示调用本类其它构造方法
注意:只能在构造方法的第一行
super关键字 表示父类对象
super.属性 一般父类的属性私有 无法直接使用
一般不用
super.父类方法 指明调用父类的方法
方法覆盖语法
super(); 表示调用父类的构造方法 可以传参数 指定调用哪个
注意,只能在构造方法的第一行
任何构造方法的第一行,默认就是super();
和方法相关的语法:
(1) 方法的重载 Overload
一般在一个类中 方法名相同,参数表不同(类型 数量 顺序)
返回值类型是否相同不作为重载的依据
用途:简化用户的使用
(2)方法的覆盖(重写):Override
子类如果对父类的方法不满意,可以覆盖父类的方法。也称为重写,能够将父类的方法覆盖
@Override // 标注,覆盖父类的方法,用于编译器检查是否有覆盖
在实际运行时,会使用子类覆盖后的方法
注意:1> 方法的三要素要相同:方法名 参数表 返回值类型
2> 访问控制修饰符范围不能更窄
父类eat public
子类eat private 不能 只能写public
3> 声明抛出的异常类型不能更多
面向对象编程基本思路
关键 :抽象 类 和对象
分析 设计 得到类
属性(数据) 构造方法(初始化数据) 方法(功能 操作数据)
通过类创建对象并使用
多态的前提:没有继承就没有多态
使用父类的引用指向子类对象
Animal a1 = new Cat();
父类 变量 子类
编译时类型 运行时类型
编辑器理解 JVM理解
2、多态的三大定理:重要
(1)对象不变 new Cat(); 不能变为Dog对象
(2)编译时只能调用编译时类型已定义的方法
(3)运行时调用的是运行时子类类型覆盖后的方法
前提:非静态static
由于定理2不能调用子类特有的方法
多态:意义深远,优势较多,不足可以忽略
数据类型转换
1. 自动类型转换
常数在表数范围内 范围小->范围大
引用类型 子类->父类 基本类<->包装类型
2. 强制类型转换
其他
Animal a1 = new Cat();
Cat c1 = (Cat)a1;
c1.catchMouse();
异常:
ClassCastException
编译时可以通过,运行时抛出异常:类型转换异常
属于运行时异常,需要在编程时避免
方法:在转化之前先判断a1指向对象的类型
关键字:instanceof 是不是
// 避免ClassCastException 类型转换异常。建议在强制类型转换前先判断类型
if(c2 instanceof Dog) {
Dog d1 = (Dog) c2; // false 不会执行
d1.watchHome();
System.out.println("true-dog");
}
Dog d1=(Dog) c2;
d1.watchHouse();
以上代码
Exception in thread "main" java.lang.ClassCastException: day08.Cat cannot be cast to day08.Dog
at day08.TestAnimal.main(TestAnimal.java:114)
3. 多态的分类
(1)基本类型的多态 本质:自动类型转换 提升
double d1 = 'A'; //char->double 65.0
double d1 = 123; //int->double 123.0
double d1 = 123.5F; //float->double 123.5
double d1 = 123.5;
(2)类多态 引用类型
前提:使用父类引用指向子类对象
Animal a1 = new Cat();
Animal a2 = new Dog();
父类 子类
编译时类型 运行时类型
编译器 JVM
(3)方法多态
1)编译时多态 Overload 重载
编译时决定调用哪个方法
2)运行时多态 Override
运行时决定调用哪个方法
多态定理3:运行时执行的是子类覆盖后的方法,取决于子类是否被覆盖父类的方法
如果子类未覆盖 还是父类的方法
4. 多态的应用
前提:使用父类引用指向子类对象
将子类对象当做父类类型看待
Animal a1 = new Cat();
Animal a2 = new Dog();
父类和子类 父类更抽象
面向父类编程 -> 面向抽象编程 -> 面向通用编程
思路:设计的程序,通用性强,降低成本 可复用性 易维护性
更适合参与设计,比直接使用有些难度
(1)方法的参数表中使用多态
需求:动物园需要喂养动物
如果需求变化 增加方法 对结构的影响较大
改设计:我们只需要修改方法的实现,影响较小
软件设计的基本原则,开闭原则
对扩展开放,对修改关闭
软件需求的增加 会引起代码的变化。功能的增加,对软件影响很小,只需要添加新的代码,无需修改旧的结构
目的:提高可复用性 易维护性
(2)在返回值类型中使用多态
需求2:动物园需要对外提供不同的动物
结合设计模式 工厂模式 Factory
提示:设计模式用于软件设计,目的提高软件的优势
系统分析:问题空间 OOA
根据名词 动词将问题进行分类和归纳
系统设计:解空间 OOD
软件建模 使用UML语言
UML统一建模语言 特点使用各种图形表达设计
(1)静态建模
面向对象的三大特征:封装 继承 多态
1. 多态:一种类型 呈现多种状态
主要关注:类多态 方法多态
2. 多态的前提:继承 is-a关系
父类的引用指向子类对象
Animal a1 = new Cat();
父类 子类
编译时类型 运行时类型
编译器 JVM
3. 多态的三大定理:
对象不变 new Cat();不会变成Dog对象
编译时只能调用编译时类型已定义的方法
运行时调用的是运行时类型覆盖后的方法--非静态static
4. 对定理2的补充
无法调用子类特有的方法 采用强制类型转换
需要注意:类型的判断 避免ClassCastException
5. 多态的分类
基本类型多态 本质:自动类型转换 提升
(1) 方法的重载 Overload
编译时多态
编译时决定调用哪个方法
(2)方法的覆盖(重写):Override
运行时多态
运行时决定调用哪个方法
6. 多态的应用
(1) 在方法的参数表中使用多态
public void feed(Animal a1, Animal a2)
参数可以传入任何Animal以及子类的对象
public void foo(Object obj)
参数可以传入任何对象
(2) 在方法的返回值类型使用多态
结合设计模式:工厂模式 降低代码的耦合度 解耦合
public class AnimalFactory{
public static Animal getAnimal(int msg){
Animal a1 = null;
switch(msg){
case1 : a1 = new Cat(); break;
case2 : a1 = new Dog(); break;
default: System.out.println("无效的消息);
}
return a1;
}
}
Animal a1 = AnimalFactory.getAnimal(1);
Animal a1 = AnimalFactory.getAnimal(2);
static final abstract
静态的 不变的 抽象的
是重要的关键字 修饰词
为面向对象编程提供
目的:参与设计
一、static关键字 静态的
作为修饰符 可以修饰:属性 方法 代码块 内部类
注意:不能修饰局部变量
属性属于成员变量,是类中的一部分。局部变量是方法中定义的,不能加静态修饰符
特点:static修饰的资源会在类加载时执行或者初始化
static成员可以通过类名直接调用
Integer.MAX_VALUE 属性 不加括号
Math.random(); 方法 加括号,方法有参 无参
AnimalFactory.getAnimal(1);
TestLeapYear.isLeapYear(2013);
类加载:class load
当JVM第一次使用每个类时,将其*.class文件读入JVM内存,存于Code区,可以作为模板来创建对象,使用其方法
类加载的时机:
1> new Student(); 会加载Student类
只声明引用Student stu; 不会加载
2> 类名.静态成员
Arrays.sort(ds);
会先加载java.util.Arrays类
补充:JVM启动时会提前加载java.lang下所有类,比如java.lang.String Integer Math...
3> Class.forName("day08.Animal");
手动加载day08.Animal类
目的:就是为了加载一个类 类必须写全名
JVM内存的三大区域
栈区 Stack 局部变量
堆区 Heap 对象
方法区 Code 类的信息 静态资源
1. static 修饰属性
不加static:实例方法 通过对象.调用。实例变量 每个对象(实例)拥有一份 id name age
加了static:静态方法 通过类名.直接调用。类变量 整个类只有一份(对象共享一份)
class Student{
int no; //学号
static int cno; //班级号
}
关键字 static 不能作为包名 类名
栈引用 堆对象 code类属性
s1 no Student
cno
The static field Student.cno should be accessed in a static way
这个 静态 属性cno 建议 访问 静态方式
结论:静态成员 一般直接通过类名访问 建议直接通过类名访问静态成员
s1.cno 没有必要 属于类的
建议 Student.cno
哪些类不用创建对象
Math类 Arrays类
当无需保存具体数据时,只需使用其方法时,可以不用创建对象实例,只通过类名.静态方法
Math.random();
Arrays.sort(ds);
好处:减少大量不必要对象的创建,减少堆空间,节省Heap空间。堆空间的对象如果越来越多,垃圾越来越多,GC很频繁,效率会降低
结论:当一个类中几乎都是static静态方法,称之为工具类
比如java.lang.Math java.util.Arrays类
util包:工具包
使用时,无需创建对象,直接通过类名调用方法,只使用其方法
如果new Math();报错 ,工具类方法私有,直接调用,没必要创建对象
private Math() {}
面向对象的三大特性:封装 继承 多态
多态:
1. 含义:一种类型,能够呈现多种状态
类多态 方法多态
2. 多态的前提:继承 is-a
使用父类的引用指向子类对象
Animal a1=new Cat();
Animal a2=new Fish();
Non-static field 'm' cannot be referenced from a static context
非静态属性不能被指向静态内容
静态方法不能访问非静态成员(属性 方法)
通过类名调用静态方法时,对象还未创建,未分配对象空间,尤其是实例变量
为什么main方法设计为static方法?
public class Hello {
public static void main(String[] args) {
int c = MyMath.add(1, 2);
System.out.println(c);
}
}
原因: javac Hello.java-> Hello.class
运行 java Hello 启动JVM进程,加载Hello.class类,执行Hello.main方法,可以通过类名直接调用方法
(3)static修饰代码块--静态代码块
代码块{}
可以作为:类体 方法体 分支体 循环体 实例代码块 静态代码块
class Foo{
{
实例代码块 对象创建时先于构造方法执行
}
static{
静态代码块,在类加载时执行 仅一次
适合写初始化系统环境的程序
比如加载缓存
}
public Foo(){
伴随对象的创建而执行
}
}
示例Demo
package day09.sta;
class Foo {
{ // 对象创建时 先于构造方法执行
System.out.println("实例代码块...4");
}
static {
// 在类加载时执行 仅一次
System.out.println("静态代码块...5");
}
public Foo() {
// 伴随对象的创建执行new
System.out.println("Foo()...6");
}
}
public class TestStatic3 {
static {
// 在类加载时执行 仅一次
System.out.println("静态代码块...3");
}
public static void main(String[] args) {
System.out.println("begin...1");
Foo f1 = new Foo();
Foo f2 = new Foo();
System.out.println("end...2");
}
}
运行结果:
静态代码块...3
begin...1
静态代码块...5
实例代码块...4
Foo()...6
实例代码块...4
Foo()...6
end...2
java软件如何提升系统性能?
主要硬件:硬盘 内存 CPU
空间大 速度慢 速度较大 速度最快
1> 使用缓存 Cache
思想:使用空间换取时间
内存空间 访问时间
2> 使用单例
4. static修饰内部类
class Outer{
class Inner1{ //成员内部类
}
static class Inner2{ //静态内部类
}
}
5. 对多态定理3的补充说明
定理3:运行时调用的是运行时类型覆盖后的方法
前提:非static
原因:静态方法不能被覆盖的,就没有多态
调用时取决于编译时类型
看左侧类调用的是super还是sub
6. static的应用
设计模式--单例模式 Singleton
含义:保证一个类在系统中最多创建一个实例
好处:能避免对象的大量创建,减少系统垃圾,降低GC的启动频率,由于GC消耗系统性能,从而提高java系统性能
哪些类适合 哪些类不适合
Student类 不适合 需要通过不同的对象实例来区分不同的学生数据--属性
Math类 适合 不需要大量的Math类对象来保存数据 只需要使用其方法
甚至:Math类不可能有实例 因为构造方法私有
完全可以通过类名.静态方法
7.如何实现单例?
(1)构造方法私有
(2)提供一个静态的方法获取单例
(3)提供一个静态的属性来保存单例
进程:等待着操作系统OS调度的程序(内存中)
IE浏览器 记事本 Eclipse进行
进程间的通信比较麻烦
线程:一个进程分为多个线程同时执行
线程更便于数据通信
多线程并发执行时 要考虑线程的安全问题
对被共享的数据加以保护 机制:锁机制
二、final关键字 不变的(稳定)
作为修饰符 可以修饰变量(成员变量 局部变量)、方法、类
1.final修饰变量
不加final 变量
加了final 常量 一经赋值 不可改变
修饰成员变量-常量
class Person{
int age; // 成员变量
final int m = 1; // 常量
final int n; // 常量
public static final int max_age = 100;
// 要么在声明时直接初始化 要在构造方法中
public Person(){
n=1;
}
}
2. 修饰局部变量->常量
定义在方法中的变量 包括参数表中
final修饰方法 不能被子类覆盖。最终 不变
3. final修饰类
不能被继承(扩展)
java.lang.String类就是一个final类
static final abstract修饰符能够增加面向对象功能
应用于设计 抓住其规则
一、static关键字 静态的
作为修饰符 可以修饰 属性 方法 代码块 内部类,但不能修饰局部变量
特点:static的成员或代码块 会在类加载时被执行或初始化
static资源(成员) 可以通过类名直接访问
类加载:class load JVM第一次使用某个类 将*.class文件读入JVM code区,之后就可以使用该类
类加载时机:
1)new Student();
2)类名.静态成员
3) class.forName("类的全名");手动加载
1. 修饰属性
实例变量 -> 类变量
每个对象拥有一份 整个类拥有一份
id name age
建议使用类名直接访问 Math.PI
2. 修饰方法
实例方法 -> 静态方法
必须通过对象.调用 通过类名直接调用
可以访问实例变量
结论:静态方法不能访问非静态成员(属性 方法)
BS/MS
使用静态方法的时候对象未创建
非静态new
特点:如果一个类中所有方法都是静态方法,称为工具类 Math类 Arrays类 主要提供方法
无需创建对象 直接通过类名调用 大大减少对象创建
3. 修饰代码块
实例代码块 -> 静态代码快
对象创建时先于构造调用 类加载时执行
class Foo{
static{
类加载时执行
用于完成系统初始化的代码
比如:加载缓存的程序
思想:拿空间换取时间
内存空间 访问时间
}
}
5. 在运行时调用的是运行时类型覆盖后的方法(非static)
原因:静态方法不能被覆盖 没有多态
主要根据编译时类型找方法
建议:直接根据类名调用,更明确
保证一个类在系统中最多只能创建一个实例(对象)Instance
作用:能够提供系统性能
6. static的应用,设计模式--单例模式
public class MyMath{
// 提供静态属性保存单例
private static MyMath my=new MyMath();
// 构造方法私有
private MyMath(){}
// 提供静态方法获取单例
public static MyMath getInstance(){
return mm;
}
}
二、final关键字 不变 最终版本
作为修饰符 可以修饰
变量(成员变量 局部变量)、方法、类
1. 修饰变量
从变量->常量 一经赋值 不可改变
(1)成员变量
final int a=1;
要么在声明时初始化,要么在构造方法中初始化
不如设计为公开的 静态的常量
public static final double PI = 3.1415926
要么在声明时初始化 要么在静态代码块中初始化
(2)局部变量
public void change(int a,final int[] ds2){
int m=1;
int n=2;
final int k=3;
}
2. 修饰方法 不能被子类覆盖
3. 修饰类 不能被继承
比如 java.lang.String类就是final类 不变模式
三、abstract关键字 抽象的
作为修饰符 可以修饰 方法 类
1.当父类中某个方法不知如何实现时,可以将其定义为抽象方法,将方法体去掉,使用;代替,添加abstract修饰符,该抽象方法最终由子类实现(覆盖)
2.java规定:有抽象方法的类也必须是抽象类,也使用abstract修饰,注意,抽象类不能直接new对象,但可以作为父类引用指向子类对象,同样满足多台三大定理
抽象语法
1.修饰方法
[修饰符]abstract 返回值类型 方法名(参数表)[throws 声明抛出的异常类型,...];
2.修饰类
[修饰符]abstract class类名 [extends父类] [implements接口1,接口2...]
{
一般具有抽象方法
}
抽象类不能直接new对象 new Animal();
Animal a = new Cat(); 可以作为父类引用指向子类对象 同时满足多态三大定理
1. 当父类中某个方法不知如何实现时,可以将其定义为抽象方法,将方法体去掉,使用;代理,添加abstract修饰符,该抽象方法最终由子类实现(覆盖)
2. java规定:有抽象方法的类也必须是抽象类,也使用abstract修饰,注意:抽象类不能直接new对象,但可以作为父类引用指向子类对象,同样满足多态三大定理
4、注意点
1)抽象类中有构造方法,可以初始化属性
抽象类中可以有实例变量,可以通过构造方法初始化
2)抽象类不可以被实例化 new Animal();不行
3)可以定义抽象类的引用,通过此引用指向子类对象同样满足多态的三大定理
Animal a1 = new Cat();
a1.eat(...);
4)--个类B如果继承抽象类A,就必须实现A类中的抽象方法
如果B类不实现抽象方法,也必须定义为抽象类
5) abstract修饰的方法最终一定会被非抽象子类实现(覆盖)
修饰符位置不分先后
public static void main 习惯先写访问控制修饰符
static public void main 一样
四、接口 interface
1. 含义
接口也是一种引用类型
接口也可以理解为一种特殊的抽象类
1) 所有的属性都是公开的静态的常量
使用public static final修饰
2) 所有的方法都是公开的抽象的方法
使用public abstract修饰
接口不能有构造方法
不能new接口
1>
class ClassA{
public static final int A = 1;
public static final int B = 2;
public abstract void m1();
public abstract void m2();
}
由于比较抽象 不如设计为接口interface
interface IA{
int A=1;
int B=2;
void m1();
void m2();
}
2. 接口的用法
类继承类 extend
类实现接口 implements
接口继承接口 extend
都具备"is-a"关系
(1)一个类可以实现一个接口
class Class1 implements IA{
需要实现m1和m2方法(覆盖语法)
}
(2)一个类可以实现多个接口
interface IB{
public void m3();
}
class class2 implements IA, IB{
public void m1();
public void m2();
public void m3();
}
(3)一个类可以继承一个父类,同时实现一个或多个接口
class Myclass{
public abstract void ma();
}
class Class3 extends Myclass implements IA,IB{
}
继承父类和实现接口的区别
继承父类 只能一个
实现接口 可以多个
徒弟 extends 师傅 implements 干爹1,干爹2,...
(4)如果一个类只实现接口中的部分方法,可以定义为抽象类
class Class4 implements IA{
只实现m1方法
}
(5) 一个多个接口可以继承一个或者多个接口 extends
interface IC extends IA,IB{
}
用途:将IA IB接口的功能进行合并 复用
发现:接口可以多继承
class Class5 implements IC{
实现m1 m2 m3方法
}
3. 接口的分类 用途:设计、制定标准、规范
(1) 普通借口 主要定义方法
interface EmpDao{ // 接口
public Emp[] findAll(); //查询所有的员工信息
...
}
class EmpDaoImpl implements EmpDao{ // 实现
public Emp[] findAll(); //查询所有的员工信息
写程序访问数据库获取数据...
}
接口指向子类对象
面向接口编程
(2)常量接口 主要定义属性
String color = "Red"; "blUe" "grEEn"
容易写错 可读性不够好
interface Color{
String RED= "Red";
String BLUE= "Blue";
String GREEN= "Green";
}
使用时Color.RED Color.BLUE Color.GREEN
好处:准确性高 可读性好
编译器会检查
(3) 标识接口
既没有属性 也没有方法
作为一种特殊的标识 表示具备某种规范
实现了该接口类的对象 可以在网络中传输
对象序列化:将对象数据变为字节流 在网络中传输
java.io.Serializable接口 对象序列化接口 对象序列化:将对象在网络中传输
对象-> 字节流 序列化
字节流-> 对象 反序列化
前提:需要实现Serializable接口
源代码
package java.io;
public interface Serializable {
}
4. 接口的应用
(1)接口变相达到多继承的语法
一个类可以继承一个父类 并实现多个接口
class Class3 extends Myclass implements IA,IB{
子类 父类 父接口
实现类 is-a
}
(2)形成一种主次分明的设计
如何设计?建模 类图UML
通过类创建对象(实例) 保存数据(属性) 操纵数据(方法) 进行应用
二、接口 interface
1. 含义
接口是一种引用类型,常用于设计
接口可以理解为特殊的抽象类
1> 所有的属性都是公开的 静态的常量
使用public static final修饰
2> 所有的方法都是公开的 抽象的方法
使用public abstract修饰
3> 没有构造方法
原因:i 常量已经初始化了,无需构造方法
ii super();指的是父类
2. 接口的用法
以下都具备:is-a关系
类继承类 extends 单继承
类实现接口 implements 多实现
接口继承接口 extends 多继承
一个类可以实现一个或多个接口
一个类可以继承一个父类
3. 接口是制定规范、标准、分工、解耦合的极好的工具
JDBC技术 Java语言 访问数据库
Java DataBase Connectify
抽象类和接口的异同点?
(1) 定义接口用interface,定义抽象类abstract class
(2) 实现接口用implements,继承抽象类用extends
(3) 接口可以多继承,抽象类只能单继承
(4) 接口没有构造方法,抽象类有构造方法
(5) 接口所有的属性都是public、static、final修饰
接口所有的方法都是public、abstract修饰
(6) 接口和抽象类都不能直接实例化使用不能new,但是可以拿接口或抽象类类型的引用指向子类对象具备多态的特性面向抽象(父类、接口、通用)
API应用编程接口
比如JDK为我们提供了许多类和接口 为我们编程提供最底层的支持
比如String类用于表示字符串
比如Scanner类用于数据的输入
比如Math类用于算术的运算
比如Arrays类用于数组的工具类 排序等