Java面向对象编程
Java面向对象编程
- 数据类型
- 基本数据类型:byte(位),short(短整数),int(整数),long(长整数),float(单精度),double(双精度),char(字符),boolean(布尔值)
- 数组
- 数组排序:java.util.Array.sort(data);
- 数组复制:System.arraycopy(原数组,原数组起始点,目标数组,目标数组起始点,拷贝长度)
- 数据库中表和Java类之间的关系
- 数据实体表的定义 = 类的定义;
- 表中的字段 = 类的成员属性;
- 表的一行记录 = 类的一个实例化对象;
- 表的多行记录 = 对象数组;
- 表的外键关联 = 引用关联;
- 数据表与java类之间的映射的解决步骤
- 先抛开所有的关联字段不看,写出类的基本组成
- 通过引用配置关联字段的关系
- String类
1 | - 字符串比较: |
- 继承
继承的规则:
- 不能多重继承,可以多层继承,层次不建议超过3层
- 父类需要有无参构造
- super()放在派生构造类的首行,表示子类调用父类构造的语句,在父类没有无参构造时,子类需要用super()明确调用有参构造
- 派生类实例化对象时,会首先实例化父类对象,目的是为了给所有属性进行空间分配
- 子类可以继承父类的一切,但是对于父类私有的属性,只能通过方法间接访问,不能直接访问
复写:
- 子类定义了与父类方法名称相同,参数类型和个数完全相同的方法,就是方法的复写
- 在子类复写父类的情况下,可以通过Super.方法名,调用已经被重写的父类方法
- 子类复写的方法,不能拥有比父类更为严格的访问控制权限public>default>private
- 父类private定义的方法不能被复写
属性覆盖:
- 子类定义了一个和父类名称相同的属性名
final:终结器
- 定义不能被继承的类
- 定义不能被复写的方法
- 定义不能被修改的常量
override和overloading的区别:
- overloading:重载 概念:方法名称相同,参数的类型及个数不同 权限:无限制 ,在进行方法重载的时候并未对返回值做出限制
- override:重写/复写 概念:方法名相同,参数类型及个数,返回值相同 权限:被覆写方法不能拥有更严格的控制权限
- 多态
- 对象向上转型:创建一个子类对象,把它当作父类来看待,向上转型一定是安全的,但是一旦发生向上转型为父类对象,就不能调用子类原本特有方法
- 对象向下转型:是子类向上转型的还原,也就是将父类对戏那个还原为本来的子类对象
- instanceof:安全向下转型的测试
- Object类
- object类是所有类的父类
- 子类可以通过重写Object的toString方法来实现对象信息的输出
- 对象比较:可以通过重写equals方法,指定规则比较
- 抽象类的定义与使用
定义:用abstract来修饰的类,抽象类的主要作用在于对子类中覆写方法进行约定,抽象类中必然有抽象方法,抽象方法是用abstract修饰的没有方法体 的方法
抽象类不是完整的类,不能实例化,若想使用抽象类则
> 抽象类必须提供有子类,子类使用extends继承一个抽象类
> 抽象的子类(不是抽象类)一定要重写抽象类中的全部抽象方法
> 抽象类的实例化可以利用对象多态性通过子类向上转型的方式完成
使用抽象类:
> 抽象类中可以提供构造方法,但是抽象类无法直接实例化,须由子类的完成实例化操作
> 抽象类中可以没有抽象方法,但是有抽象方法的类,必然是抽象类,须由abstract修饰
> 抽象类之中主要目的是进行过度操作使用,所以当你要使用抽象类进行开发的时候,往往都是在你设计中需要解决继承问题时所带来的代码重复处理
> 抽象类可以有static静态方法,该方法不受抽象类影响
> 抽象类本质是加强型的类,可以描述一切的有关的现实事物,因此抽象类的设计应该是比类更高一层的定义
- 包装类
- 对象型包装类(Object的直接子类):Boolean,Character
- 数值型的包装类(Number的直接子类):Byte,Short,Integer,Long,Float,Double
Number类中的方法:
- byteValue():从包装类中获取byte数据
- shortValue():从包装类中获取short数据
- intValue():从包装类中获取int数据
- longValue():从包装类中获取long数据
- floatValue():从包装类中获取float数据
- doubleValue():从包装类中获取double数据
装箱与拆箱操作:
- Interger类:Interger(int value)
- Double类:Double(double value)
- Boolean类:Boolean(boolean value)
- 接口(interface)
抽象类与普通类相比最大的优势在于:可以实现对子类覆写方法的控制,但在抽象类里面可能依然会保留有一些普通方法,而普通方法里面可能会涉及到一些安全或隐私的操作问题,那么这样在进行开发的过程之中,如果要想对外部隐藏全部的隐藏细节,则就可以通过接口来进行描述
接口可以理解为最纯粹的抽象类(最原始的定义接口之中是只包含抽象方法和全局常量)
- 接口需要被子类实现,一个子类可以实现多个接口
- 子类(如果不是抽象类)那么一定要覆写接口中的全部抽象方法
- 接口对象可以利用子类对象的向上转型进行实例化
- 接口虽然可以成功定义,但是在实际开发中,实现接口的可能是抽象类,一个抽象类可以实现多个接口,一个普通类可以继承一个抽象类,并且可以实现多个父接口,但是要求先继承后实现
- 虽然接口无法继承一个父类,但是一个接口却可以继承多个父接口,此时称接口的多继承
在实际开发中,接口的使用有三种形式:
- 进行标准设置
- 表示一种操作的能力
- 暴露远程方法视图
- 泛型
泛型就是参数化类型
- 适用于多种数据类型执行相同的代码
- 泛型的类型在指定时使用
优点:使用泛型时,在实际应用之前类型就已经确定了,不需要强制转换
使用范围:
- 主要使用在集合中
- 泛型类:只能用在成员变量上,只能使用引用类型
- 泛型接口:只能用在抽象方法上
- 泛型方法:返回值前加&ItT>
泛型的继承(?是通配符):
- extends(上限):指定的类必须继承某个类,或实现某个接口(不是implements),即? extends List
- super(下限):? extends List
- 常见包
- java.lang:String,Number,Object等类,自动导入
- java.lang.reflect:反射机制处理包,所有设计从此开始
- java.util:工具类的定义,包括数据结构的定义
- java.io:输入输出流操作的程序包
- java.net:网络程序开发包
- java.sql:数据库编程的开发包
- java.applet:Java的最原始的使用形式,直接嵌套在网页上执行的程序类
- 现在的程序以Application为主(有主方法的程序)
- java.awt,java.swing:Java的图形界面开发包(GUI),其中awt是属于重量级组件,而swing是轻量级组件
- 生成jar文件
对程序打包编译:javac -d Message.java;
此时会形成cn包,包里面有相应的子包与*.class 文件,将其打包为mldn.jar
jar -cvf mldn.jar cn
“-c”: 创建一个新的jar文件
“-v”:得到一个详细输出
“-f”:设置要生成的jar文件的名称,本初定义的是”mldn.jar”
set calsspath=.;jar包存在路径
- 访问权限
No. | 访问范围 | private | default | protected | public |
---|---|---|---|---|---|
1 | 同包同类 | y | y | y | y |
2 | 同包不同类 | y | y | y | |
3 | 不同包的子类 | y | y | ||
4 | 不同包的所有类 | y |
- UML图形
类图:显示模型的静态结构,反应类内部结构以及其与其他类之间的关系
>类名称
>属性
>方法
时序图:反应代码的执行流程
用例图:描述程序的执行分配
- 设计模式
控制实例化产生个数的设计操作
单例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39//饿汉式
class Singleton{
private static final Singleton INSTANCE=new Singleton();
private Singleton(){}
public static Singleton getInstance(){
if(instance==null){
instance=new Singleton();
}
return instance;
}
public void print(){
System.out.println("www.mldn.cn");
}
}
public class JavaDemo{
public static void main(String args[]) {
Singleton instance=null;
instance=Singleton.getInstance();
instance.print();
}
}
//懒汉式
class Singleton{
private static Singleton instance=new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
public void print(){
System.out.println("www.mldn.cn");
}
}
public class JavaDemo{
public static void main(String args[]) {
Singleton instance=null;
instance=Singleton.getInstance();
instance.print();
}
}Singleton程序的特点
>代码如上,可以将懒汉式和饿汉式都写上;
>特点:构造方法私有化,类内部提供static 方法获取实例化对象,不管外部如何操作,永远只有一个实例化提供
多例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27class Color{
private static final Color RED=new Color("红色");
private static final Color Green=new Color("绿色");
private static final Color Blue=new Color("蓝色");
private String title;
private Color(String title) {
this.title=title;
}
public static Color getInstance(String color){
switch(color){
case "red":return RED;
case "green":return GREEN;
case "blue":return BLUE;
default:return null;
}
}
public String toString(){
return this.title;
}
}
public class JavaDemo{
public static void main(String arg[]){
Color c=Color.getInstance("green");
System.out.println(c);
}
}
- 枚举
- 主要作用:用于定义有限个数对象的一种结构(多例设计),枚举就属于多例设计
1 | enum Color{ |
枚举的本质:相当于一个类,但是这个类默认会继承Enum类
方法:
No. 方法名称 类型 参数类型 01 protected Enum(String name,int ordinal) 构造 传入名字和序号 02 public final String name() 普通 获得对象名字 03 public final int ordinal() 普通 获得对象序号 总结:在枚举中,每一个对象的序号都是根据枚举对象的顺序来决定的
问:enum与Enum的区别?
答:1.enum:是从JDK1.5之后提供的一个关键字,用于定义枚举类;
2.Enum:是一个抽象类,所以使用enum定义的类就默认继承此类
定义枚举结构:枚举虽然也是多例的设计模式,但是不同点在于,枚举不能定义私有的构造方法,而多例可以
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17enum Color{//枚举类
RED("红色"),GREEN("绿色"),BLUE("蓝色");//枚举对象要写在首行
private String title;//定义属性
private Color(String title){
this.title=title;
}
public String toString(){
return this.title;
}
}
public class JavaDemo{
public static void mian(String args[]){
for(Color c:Color.values()){
System.out.println(c.ordinal()+"-"+c.name()+"-"+c)
}
}
}总结:
- 枚举对象要写在首行
- 枚举类也可以调用接口
- 枚举类可以直接定义抽象方法。并且要求每个对象都要独立覆写此方法
- 内部类
1 | class Outer{//外部类 |
内部类存在的意义:可以通过内部类访问外部类的私有属性
1 | package inner_class; |
1 | package inner_class; |
static 定义的不管是类还是方法,只能访问static成员,所以static定义的内部类只能够访问外部类的static属性或方法,这个时候Inner类是一个独立的类,如果此时要想实例化Inner类对象。需要根据外部类.内部类实例化对象即可
static定义内部类的形式并不常用,static定义内部接口的形式最为常用
1 | package inner_class; |
之所以用static定义内部接口,主要是因为这些操作是属于一组相关的定义,有了外部接口之后可以更加明确得描述这些接口的主要目的和功能
1 | //方法中定义内部类 |
内部类可以定义在任意结构中,这就包括:类中,方法中,代码块中,但是从实际开发来讲在方法中定义内部类的形式较多;
- 函数式编程
- Lambda表达式
Lambda表达式格式:
- 方法没有参数:()->{};
- 方法有参数:(参数,参数)->{};
- 只有一条语句返回:(参数,参数)->语句;
Lambda表达式注意点:主要用来定义行内执行方法类型接口
1 | package inner_class; |
- 方法引用
引用最大的特点是可以进行内存的指向处理,但是在传统开发之中所使用的只是对象的引用操作,而从JDK1.8之后提供了方法的引用,即:不同的方法名称可以描述同一个方法。
引用静态方法:类名称::static方法名称;
引用某个实例对象的方法:实例化对象::普通方法;
引用特定类型的方法:特定类::普通方法;
引用构造方法:类名称::new;
1
2
3
4
5
6
7
8
9
10
11
12
13
14package inner_class;
//函数式接口
//P描述的是参数,R描述的是返回值
interface IFunction<P,R>{
public R change(P p);
}
public class lamada {
public static void main(String[] args) {
IFunction<Integer,String> fun=String::valueOf;
String str=fun.change(100);
System.out.println(str.length());
}
}
//利用方法引用这一概念可以为一个方法定义多个名字,但是要求必须是函数式接口1
2
3
4
5
6
7
8
9
10
11//函数式接口
//P描述的是参数
interface IFunction<P>{
public int compare(P p1,P p2);
}
public class lamada {
public static void main(String[] args) {
IFunction<String> fun=String::compareTo;
System.out.println(fun.compare("A","b"));
}
}
- 内建式函数接口
存在于java.util.function包,可以不用创建大量的@FunctionalInterface//函数式接口
功能性性函数式接口:String类:以startsWith为例
1
2
3
4
5
6
7
8
9package inner_class;
import java.util.function.*;
public class lamada {
public static void main(String[] args) {
Function<String,Boolean> fun="**Hell0"::startsWith;
System.out.println(fun.apply("*"));
}
}消费型函数式接口
1
2
3
4
5
6
7import java.util.function.*;
public class lamada {
public static void main(String[] args) {
Consumer<String> con= System.out::println;
con.accept("Hello World");
}
}供给型函数接口:以String类中toLowerCase()为例,这个方法没有参数,但有返回值
1
2
3
4
5
6
7
8import java.util.Locale;
import java.util.function.*;
public class lamada {
public static void main(String[] args) {
Supplier<String> sup="HELLOW,WORLD"::toLowerCase;
System.out.println(sup.get());
}
}断言型函数接口:以String类中的equalsIgnoreCase()方法为例
1
2
3
4
5
6
7import java.util.function.*;
public class lamada {
public static void main(String[] args) {
Predicate<String> pre="mldn"::equalsIgnoreCase;
System.out.println(pre.test("Mldn"));
}
}
- 链表的定义与使用
![image-20210513205736962](../../../我的坚果云/基于Java/Java学习路线/阶段1 Java语言基础/img/image-20210513205601920.png)
链表结构:
数据保存:public void add(E e)
注意点:进行链表操作的过程中为了避免转型的异常应该使用泛型,同时也应该设计一个链表的执行接口,并且具体实现该接口的时候还应该通过Node类做出节点的关系描述
1 | interface Ilink<E>{//设置泛型避免安全隐患 |
数组与链表的区别:
- 数组的获取一个时间复杂度为1,而链表获取数据的时间复杂度为n;
![image-20210515155418544](../../../我的坚果云/基于Java/Java学习路线/阶段1 Java语言基础/img/image-20210515155418544.png)
1 | package link_table; |
1 | package link_table; |
- 面向对象设计的特征
封装行,继承,多态
面向对象程序开发的步骤
> OOA:面向对象分析
> OOD:面向对象设计
> OOP:面向对象编程