Java 基础知识点梳理

知识框图

Java_map

​ 图 1 Java 知识框图

(画的图稍有些宽,Markdown 编辑器按比例压缩了,图片均放在同级 img 目录下)

###Java 基础 和 面向对象

#####跨平台性

Java 是一门跨平台的语言,它的跨平台性主要体现在 JVM 的设计上,由于 JVM 的存在,使得 Java 成为了一门跨平台的语言。

在整个 Java SE 的知识体系中,基础板块包括数据类型、运算符、流程控制、数组等内容;

#####面向对象基本概念

面向对象是整个 Java 中最为核心的一个思想,面向对象的存在是相对于面向过程而言,面向过程主要侧重的是功能的行为,或者说是执行该功能的对象,而面向对象侧重的是具备该功能的对象, 面向对象更加强调人和对象在日常行为中采用的思维和法则,如:抽象、封装、聚合、多态等。很多事物都可以抽象成对象,汽车、冰箱和人自己,世间万物皆对象。

对象中包含自身的属性和方法(即功能),可以实现某些接口和继承某个可继承的类(例如被 final 修饰的类就不可被继承),面向对象有三大特性,即:封装、继承和多态,封装性是一种对数据进行保护的设计,将属性和数据进行私有化,仅对想暴露的(通过访问修饰符:default(缺省)、public(All 类)、private(该类)、protected(同一 package))类或对象访问,封装对内部的数据进行了不同级别的访问限制,而继承其实是打破封装性的一种做法,通过继承的方式获取到父类(或者说基类)的功能和属性,继承中由于单继承的不够方便实用,而尽少的减少对封装性的打破而引入了接口,接口是对单继承的一个补充,即单继承多实现的开发模式。Java 的第三个特性是多态,是指一个类中的相同方法的不同表现形式,多态可以让具有不能内部构造的对象可以享用相同的外部接口,例如常见的 System.out.println(XXX) 方法,多态是程序扩展性的一种延伸。

Java 中设计模式分为三大类:

  • 创建型模式(5 种):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
  • 结构型模式(7 种):适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式
  • 行为型模式(11 种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式
  • 除上述 23 种外还有两类:并发型模式和线程池模式
面向对象六大原则

1. 开闭原则(Open Close Principle)

对拓展开放,对修改关闭。在程序需要修改时,不能去修改原有的代码,实现一个热插拔的效果。为了使程序的扩展性好,易于维护和升级,想要达到想要的效果,设计中需要使用接口和抽象类。

2. 里氏代换原则(Liskov Substitution Principle)

  • 任何基类出现的地方,子类一定可以出现
  • LSP (该原则简称) 是继承复用的基石,只有当衍生类可以替换掉基类,软件单位功能不受影响,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为
  • LSP 是对开闭原则的补充,实现开闭原则的关键步骤是抽象化,而基类和子类的继承关系就是抽象化的具体实现,所以里氏替换原则是对实现抽象化的具体步骤的规范

3. 依赖倒转原则(Dependence Inversion Principle)

开闭原则的基础,对接口编程,依赖于抽象而不依赖于具体

4. 接口隔离原则(Interface Segregation Principle)

使用多个隔离的接口,比使用单个接口要好,降低类之间的耦合与依赖

5. 迪米特法则(最少知道原则)(Demeter Principle)

一个实体应当尽量少的与其他实体之间发生相互作用,使得系统童年模块相对独立

6. 合成复用原则(Composite Reuse Principle)

尽量使用合成/聚合的方式,而不是使用继承。

Java 中的 23 中设计模式

初步通读一下 23 种设计模式,详细了解并记录部分常用内容。

根据网上例子挑选常用设计模式进行总结和 Demo 输出。

http://blog.csdn.net/lmj623565791/article/category/2206597

应用程序开发

JDBC 是 Java 的数据库连接,一种标准的 Java API ,用于连接 Java 语言和数据库 ,多应用于 Java EE 方向和桌面应用开发。

集合框架和数据结构暂不做总结,于 Java 数据结构及其原理解析 中总结,多线程、网络亦同,另一文档总结。

反射
  • 使用: 通过反射,可以在运行时获得程序或程序集中每一个类型的成员和成员信息、

在 Java 中,一般的对象类型均为在编译期确定,而 Java 反射机制可以动态的创建对象并调用其属性,这样的对象类型在编译期也是未知的,所以可以通过反射机制直接创建对象,即使这个对象的类型在编译期是未知的。

  • 核心:在 JVM 运行时去动态加载类、调用方法或者访问属性,不需要实现(在编程或者编译时)明确对象是谁
  • 功能
    • 1.在运行时判断任意一个对象所属的类;
    • 2.在运行时构造任意一个类的对象;
    • 3.在运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用 private 方法);
    • 4.在运行时调用任意一个对象的方法
  • 重点:运行时而不是编译时

反射主要用途

  • 通用框架开发(例如 Spring )均是配置化的,即通过 XML 文件配置 JavaBean、Action 之类,为保证通用性,可能需要根据配置文件加载不同的对象或者类,调用不同的方法,这时候就必须用到反射,在运行的时候动态加载所需要加载的对象。
  • IDE (如 Eclipse 、IDEA 等)中的代码提示,需要的也是反射。

反射基本使用

  1. 获取 Class 对象并调用方法

    • 使用 Class 类的 forName 静态方法
    1
    2
    public static Class<?> forName(String className)
    Class.forName(driver);

    在JDBC开发中常用此方法加载数据库驱动。

    • 直接获取一个对象的 class
    • 调用某个对象的 getClass 方法
    1
    2
    Class<?> klass = int.class;
    Class<?> classInt = Integer.TYPE;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // 反射使用示例
    Class<?> clz = Class.forName("android.telephony.FtTelephonyAdapter");
    if (clz == null) {
    return null;
    }
    method = clz.getMethod("getXXX", Context.class);
    if (method == null) {
    return null;
    }
    Object XXX = method.invoke(null, context);
    if (FtTelephony != null) {
    return (String) FtTelephony.getClass().getMethod("getImei",int.class).invoke(FtTelephony, 0);
    }

  2. 判断是否为某个类的实例

    一般的会用到 instanceof 关键字来判断是否为某类的实例,但同时也可以借助反射中 Class 对象的 isInstance() 方法来判断是否为某各类的实例,它是一个 Native 方法:

    1
    public native boolean isInstance(Object obj);
  3. 反射可以创建实例、获取构造器信息、获取类的成员变量(字段信息)、调用方法、利用反射创建数组等,但是具体使用场景暂时没有想法和使用经验,仅作了了解。

  4. 由于反射会额外消耗一定的系统资源,因此如果不需要动态地创建一个对象,那就不用反射,另外反射调用方法可以忽略权限检查,因此可能会破坏封装性而导致安全问题。

泛型

JDK 5 引入的一个新特性,所以可以划分到新特性类别下,目前已经是 JDK 8,所以亦可放到应用程序开发下,因为在很多开发中会用到泛型。

泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。

本质是参数化类型,即所操作的数据类型被指定为一个参数。

假设需求:排序方法,能对整形数组、字符串甚至其他类型数组进行排序,如何实现?

答案:可以使用 Java 泛型

利用泛型的概念,我们可以使用一个泛型方法来对一个对象数组排序,然后调用该方法对整形数组、浮点数数组、字符串数组进行排序。

示例小程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class GenericMethodTest {
public static void main( String args[]) {
// 创建不同类型数组: Integer, Double 和 Character
Integer[] intArray = { 1, 2, 3, 4, 5 };
Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };
System.out.println( "整型数组元素为:" );
printArray( intArray );
System.out.println( "\n双精度型数组元素为:" );
printArray( doubleArray );
System.out.println( "\n字符型数组元素为:" );
printArray( charArray );
}
// 每个泛型方法需要在返回值类型有一个参数类型声明,用尖括号分隔,如以下中的 E
public static <E> void printArray(E[] inputArray){
for (E element : inputArray){
System.out.print(element);
}
System.out.println();
}
}

泛型中可以通过声明有界的类型参数,格式为:类型参数名称 + extends 关键字 +上界

例如下面的方法:

1
2
3
4
5
6
7
8
9
10
// 比较三个值并返回最大值
public static <T extends Comparable<T>> T maximum(T x, T y, T z) { T max = x; // 假设x是初始最大值
if ( y.compareTo( max ) > 0 ) {
max = y; //y 更大
}
if ( z.compareTo( max ) > 0 ) {
max = z; // 现在 z 更大
}
return max; // 返回最大对象
}

Comparable 是排序结构,若一个类实现该接口即表明 “ 该类支持排序 ”,实现该接口的列表( List )或者数组,可以直接通过 Collections.sort (或 Arrays.sort ) 进行排序

另,实现 Comparable 接口的对象可以用作 “有序映射,如 TreeMap ”中的健或 ”有序集合 TreeSet “ 中的元素,而不需要指定比较器。

泛型类

泛型类的声明和非泛型类声明类似,除了在类名后面添加了类型参数声明部分。

和泛型方法类似,泛型类的参数声明也包含一个或者多个类型参数,参数间用逗号隔开。一个泛型参数,也称为一个类型变量,是用于指定一个泛型类型名称的标识符,因为他们接受一个或多个参数,这些类被称为参数化类或参数化类型。

示例小程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Box<T> {
private T t;
public void add(T t) {
this.t = t;
}
public T get() {
return t;
}
public static void main(String[] args) {
Box<Integer> integerBox = new Box<Integer>();
Box<String> stringBox = new Box<String>();
integerBox.add(new Integer(10));
stringBox.add(new String("字符串类型"));
System.out.printf("整型值为 :%d\n\n", integerBox.get());
System.out.printf("字符串为 :%s\n", stringBox.get());
}
}

类型通配符

一般为使用 ? 代替具体的类型参数,例如 List<?> 在逻辑上可以是 List ,List 等任何一种 List<具体实参> 类型的父类

示例小程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class GenericTest {
public static void main(String[] args) {
List<String> name = new ArrayList<String>();
List<Integer> age = new ArrayList<Integer>();
List<Number> number = new ArrayList<Number>();
name.add("icon");
age.add(18);
number.add(314);
getData(name);
getData(age);
getData(number);
}
public static void getData(List<?> data) {
System.out.println("data :" + data.get(0));
}
}

getData() 方法的参数是List类型的,所以 name,age,number 都可以作为这个方法的实参,这就是通配符的作用,输出结果是:data :icon data :18 data :314 。

类型通配符也可以定义上限,形如:

1
List<? extends Number> data

此种情况下如果仍旧使用 String 类型或者其他的去调用,会出现错误

类型通配符也可以定义下限,形如:

1
List<? super Number>

表示类型只能接受 Number 及三层父类类型,如果 Object 的实例。

小结

extends 定义该通配符所代表的类型是 T 类型的子类。

super 定义该通配符是所代表类型是 T 类型的父类。

枚举

枚举是 Java 5 中加入的特性,特殊的数据类型,是一种类 class ,又比 class 多了特殊的约束,这些约束造就了枚举类型的简洁性、安全性以及便捷性。

枚举类型是一种特殊数据类型,能够为一个变量定义一组预定义的常量。变量必须等于为其预定义的值之一。

枚举是特殊的类,可以拥有成员变量和方法。

枚举可以结合很多其他的东西使用,例如多态、泛型和反射。

可变参数

使用 … 表示可变长参数,如:

print(String… args){

}

在具有可变长参数的方法中可以把参数当成数组使用,例如可以循环输出所有的参数值。

print(String… args){

for(String temp:args)

​ System.out.println(temp);

}

并没有怎么用到过这个东西,所以暂时没有深入去看。

Lambda 表达式

Lambda 表达式是 Java 8 中引入的一种新语法,名字起源于学术界的 λ 演算(具体是什么演算暂时也没查 =-=..)。

Java 8 中引如了 Lambda 表达式和 ” 流 ”,即一种函数式的数据处理,组合式的异步编程(CompletableFuture )以及新的日期和时间 API

Lambda 表达式是一种紧凑的代码传递方式。

参考资料:https://juejin.im/post/595ce8de5188250d892f68fb

坚持原创技术分享,您的支持将鼓励我继续创作!
0%