0%

Java入门

注意:以下总结基于JDK1.8版本

JDK:Java Development Kit,Java开发工具包,包含JRE

JRE:Java Runtime Environment,Java运行时环境,包含JVM

JVM:Java Virtual Machine,Java虚拟机

JDK=JRE+开发工具(源码编译:javac命令)

JRE=JVM+核心类库(解释运行:java命令)

Java 基础语法

  • 程序基础

    1. :类是一个模板,它描述一类对象的行为和状态。

      方法:方法就是行为,一个类可以有很多方法。

      对象:对象是类的一个实例,有状态和行为。

      实例变量:每个对象都有独特的实例变量,对象的状态由这些实例变量的值决定。

    2. 基本语法:标识符以字母,$或_开始,大小写敏感,类名首字母大写,方法名小写字母开头,后续单词大写,源文件名与类名相同,主方法入口为psvm。

      Java有3种注释,单行注释,以//开头,直到这一行的结尾结束;多行注释以/*星号开头,以*/结束,可以有多行;或者以/**开头,以*/结束,如果有多行,每行通常以星号开头。

    3. 关键字

      • 48个关键字:abstract、assert、boolean、break、byte、case、catch、char、class、continue、default、do、double、else、enum、extends、final、finally、float、for、if、implements、import、int、interface、instanceof、long、native、new、package、private、protected、public、return、short、static、strictfp、super、switch、synchronized、this、throw、throws、transient、try、void、volatile、while。

      • 2个保留字:goto、const。

      • 3个特殊直接量:true、false、null。

  • 数据类型

    1. 八大基本数据类型(二进制补码表示,整数默认int,浮点数默认double)

      • 整数类型:byte(1B),short(2B),int(4B),long(8B)

      • 浮点数类型:float(4B),double(8B)

      • 字符类型:char(0/1)

      • 布尔类型:boolean(16 位 Unicode 字符)

      • 自动类型转换:byte,short,char—> int —> long—> float —> double

    2. 引用数据类型:诸如对象,数组,字符串等

  • 变量类型

    • 类变量/静态变量:独立于方法之外的变量,用 static 修饰,一份拷贝,初始化后不可改变
    • 实例变量:独立于方法之外的变量,没有 static 修饰,具有默认值,常用private
    • 局部变量:类的方法中的变量,需要初始化,作用域为方法
  • 修饰符

    1. 访问修饰符:private(方法) –> default(包) –> protected(同包子类) –> public(所有类)

    2. 非访问修饰符

      static 修饰符,用来修饰静态类方法和类变量,一般通过类名调用,所有实例共享

      final 修饰符,修饰类不能够被继承,修饰方法不能被继承类重写,修饰变量为不可修改的常量

      abstract 修饰符,用来创建抽象类和抽象方法。

      synchronized 和 volatile 修饰符,主要用于线程的编程。

  • 运算符:算术运算符,关系运算符,位运算符,逻辑运算符,赋值运算符,三目运算符?:,instanceof运算符(判断实例是否为指定类型或子类)

  • 流程控制

    1. 顺序结构;结尾

    2. 条件结构:if…else / switch…case

    3. 循环结构:while,do…while,for

      注意:break跳出当前循环代码块,continue跳转下一次循环迭代

数组

  • 声明创建
    • dataType[] arrayRefVar = new dataType[arraySize];
    • dataType[] arrayRefVar = {value0, value1, …, valuek};
    • 多维数组可直接多维分配空间,也可先高维分配,后低维分配
  • 遍历
    • 普通for循环按索引(从0开始)遍历
    • 增强for循环直接遍历元素
  • 排序
    • Arrays数组类提供sort()方法进行排序

面向对象

  • 方法

    方法==>方法头(修饰符,返回值,方法名,形参)+ 方法体

    构造方法:

    • 默认的无参数构造方法;
    • 编译器根据参数自动判断选择哪个构造方法;
    • 构造方法相互调用,便于代码复用。

    参数绑定:

    • 基本类型参数的传递,是调用值的复制。
    • 引用类型参数的传递,调用方的变量,和接收方的参数变量,指向的是同一个对象。双方任意一方对这个对象的修改,都会影响对方。
  • 重载 overload

    • 同名方法,形参列表不同,方法签名不同
    • 一般返回值是相同的
  • 封装 Encapsulation

    封装实现细节,对外提供接口(this.set+get),便于修改,减少耦合

  • 继承 Extends

    • 单继承+多重继承,根类为object,父类通用,子类具体
    • 子类访问父类protected变量和方法,重写override,返回值和形参不变,修改核心
    • 子类不会继承任何父类的构造方法,子类显式调用super()并给出参数以定位到父类相应的构造方法
    • 继承是is-a关系,组合是has-a关系
    • 可以安全地向上转型为更抽象的类型;借助instanceof判断也可以强制向下转型
  • 多态

    • 针对某个类型的方法调用,其真正执行的方法取决于运行时期实际类型的方法

    • 存在的必要条件=继承+重写+父类引用指向子类对象

    • 实现方式:重写,接口,抽象类和抽象方法

    • object类定义的三个重要方法

      • toString():把instance输出为String;

      • equals 的作用:
          引用类型:默认情况下,比较的是地址值,引用类型的比较一般都会覆写该方法

      == 的作用:
        基本类型:比较的就是值是否相同
        引用类型:比较的就是地址值是否相同

      • hashCode():计算一个instance的哈希值。
  • 接口 Implements

    • 接口比抽象类更加抽象,支持多继承
    • 接口中的成员变量只能是默认public static final
    • 接口都是抽象方法,默认public abstract省略,但可以定义default方法
    • 接口可以继承接口,扩展功能
    • 函数式接口:只能有一个抽象方法的接口,比如Comparator、Runnable、Callable
  • 抽象类和抽象方法 abstract

    • 抽象类不能实例化对象,设计原则用于子类继承,非抽象子类必须实现父类的抽象方法
    • 抽象方法只定义方法签名(只有方法名加括号),含有抽象方法必须申明为抽象类

常用类

  • String

    • 可以直接创建(存储在公共池中),也可以new创建(新建对象在堆上)

    • 常用操作:

      • 长度lenth(),拼接concat()或+
      • 索引查找indexOf(),子串查看contains()
      • 提取子串substring(),替换子串replace()
      • 格式化字符串String.format(),占位符:整数%s字符串%s浮点数%f
      • 类型转换:String.valueOf(),Integer.parseInt(),toCharArray()
    • 字符编码:ASCII(1B)=> GB2312(1B)=> Unicode(2B+)=> UTF-8(1-4B)

      java使用unicode编码表示String 和char,转换编码就是String和byte()转换(优先考虑UTF-8)

    • String 是不可变对象,操作不改变原对象,二是返回新的字符串

    • StringBuffer和StringBuilder(可变对象,链式操作自身)

  • Math

    • 数学计算库:min/max,abs,pow/sqrt,exp/log ……
  • Random

    • SecureRandom:生成安全的随机数
1
2
Random r = new Random(seed);
int temp = r.nextInt(10);
  • 大数:BigInteger和BigDecimal

  • 枚举

    • 枚举是特殊的类,为了做信息的标识和分类,声明一组带标识符的常数
    • name()获取枚举常量的名字,ordinal()获取常量定义的顺序
1
2
3
4
5
enum Color
{
RED,GREEN,BLUE;
}
Color c = Color.RED; // 不能new实例,实际上枚举实例都是唯一
  • 日期时间

    • Date和Calendar(旧API); 格式化SimpleDateFormat
    • yyyy:年、MM:月、dd: 日、HH: 小时、mm: 分钟、ss: 秒
    • LocalDateTime(新API);格式化DateTimeFormatter
  • Lambda表达式

    • 可选类型声明、可选括号、可选返回关键字
    • 形如:参数列表 -> 方法体
1
2
3
4
5
6
interface MathOperation {
int operation(int a, int b);
}

MathOperation add = (a, b) -> a + b;
add.operation(2, 6); // 8

​ 处理函数式接口时,可把实例化匿名内部类改写为Lambda表达式,简化代码

1
2
3
4
5
6
7
8
//匿名内部类
Arrays.sort(array, new Comparator<String>() {
public int compare(String s1, String s2) {
return s1.compareTo(s2);
}
});
//Lambda表达式
Arrays.sort(array, (s1, s2) -> s1.compareTo(s2));

异常处理

  • Error表示严重错误,无法处理;而Exception是运行时错误,可以被捕获并处理。不需要捕获的异常,包括Error及其子类,RuntimeException及其子类不做强制性捕获要求,剩下必须捕获的又称为检查性异常

error

  • 采用try…catch…finally捕获异常;调用printStackTrace()可以打印异常的传播栈
  • 只要是方法声明的Checked Exception,就需要在调用层捕获或者抛出
  • 日志库取代手动打印
    • java.util.logging
    • Apache第三方日志库Commons Logging,自动搜索挂接Log4j

集合类

Java标准库自带的java.util包提供了集合类:Collection,它是除Map外所有其他集合类的根接口。优点有:接口和实现分离,支持泛型,通过迭代器统Iterator一访问集合。

  • List

    • 有序列表:数组实现ArrayList和链表实现LinkedList
    • 其它操作:add、get、set、remove、size
    • 在List中查找元素时,List的实现类通过元素的equals()方法比较两个元素是否相等,因此,放入的元素必须正确重写equals()方法
1
List<T> list = new ArrayList<T>();
1
2
3
4
5
6
7
8
9
10
11
12
// 三种常用遍历方式
for(T t : list){
System.out.println(t);
}

for (int i=0; i<list.size(); i++) {
String s = list.get(i);
}

for (Iterator<String> it = list.iterator(); it.hasNext(); ) {
String s = it.next();
}
  • Map

    • 键值映射表,通过key高效查找value,Map查找速度比List快,可作为缓存
    • key无序HashMap,有序TreeMap
    • 其它操作:put(key,value)、get(key)、size()、containsKey(key)、getOrDefault(key,value)
    • map采用空间换时间的方式,key通过hashCode()计算数组索引,返回对应value
      • 作为key的对象必须正确重写equals()方法
      • 作为key的对象还必须正确重写hashCode()方法,并且保证相等对象哈希值相等(保证正确性),不相等对象哈希值尽量不相等(减少冲突)
    • hashmap内部使用数组默认大小为16,自动扩容*2,但需要重现计算索引,避免影响性能,一般提前预设定好大小
    • 哈希冲突:利用list存储不同key但hashcode相同的value
1
Map<K,V> map = new HashMap<K,V>();
1
2
3
4
5
6
7
8
9
// 遍历key
for(String key : map.keySet()){
int value = map.get(key);
}
// 遍历key-value
for(Map.Entry<String, int> entry : map.entrySet()){
String key = entry.getKey();
String value = entry.getValue();
}
  • Set

    • 不重复的元素集合,相当于只有不重复的key
    • 无序HashSet,有序TreeSet
    • 其它操作:add、remove、contains、size
    • 放入Set的元素和Map的key类似,要正确重写equals()和hashCode()方法,否则元素无法正确加入Set
1
Set<T> set = new HashSet<T>();
  • Collections.sort()
    • 第一个参数为集合实例,第二个参数为比较器Comparator(利用匿名内部类或Lambda表达式实现)
    • 重写compare方法注意,升序和降序区分:返回-1代表前者放前面,即权重小的放前面

反射 Reflection

  • 反射机制用于在程序运行期间动态变化时,对任意类或对象都能调用其字段和方法(通过Class实例获取)
  • class在JVM中动态加载,JVM为每一个class创建一个Class类型的实例(名为Class的class),而Class实例包含了该class的所有信息
1
2
3
4
5
6
7
Class c = String.class; // 静态变量获取实例
String s = (String) c.newInstance(); //通过Class实例new出对应类型实例

String s = "Hello";
Class c = s.getClass(); // 实例变量的getClass()方法

Class c = Class.forName("java.lang.String"); //传入完整类名,利用静态方法获取
  • 反射访问字段:Class实例通过getField(name)、getDeclaredField(name)方法获取Field实例,利用Field可以获取字段信息,读取或者设置对象字段,如果存在访问限制,要首先调用setAccessible(true)来访问非public字段,会破坏封装

  • 反射调用方法:Class实例通过getMethod(name, Class)、getDeclaredMethod(name, Class)方法获取Method实例,利用Method可以获取方法信息,采用invoke(instance, parameters)调用对象的某个方法

  • 反射调用构造方法:通过Class实例的方法可以获取Constructor实例,通过Constructor实例可以创建一个实例对象

  • 反射获取继承关系:getSuperclass获取父类类型,getInterfaces获取当前类实现的所有接口

  • 动态代理:动态代理不需要在编译期就实现,并且往往可以代理多个类class,拦截对真实业务对象的访问。静态代理只代理一个类class,由程序员编写,在编译器就生成相应的.class文件,由程序员调用。

    • 使用代理模式必须要让代理类和目标类实现相同的接口,客户端通过代理类来调用目标方法,代理类会将所有的方法调用,分派到目标对象上反射执行

    • 动态代理是通过Proxy类创建代理对象,然后将接口方法代理给InvocationHandler接口完成的

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
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Main {
public static void main(String[] args) {
// 实现接口的方法调用(匿名内部类)
InvocationHandler handler = new InvocationHandler() {
/**
* proxy:代表动态代理对象
* method:代表正在执行的方法
* args:代表调用目标方法时传入的实参
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method);
if (method.getName().equals("morning")) {
System.out.println("Good morning, " + args[0]);
}
return null;
}
};
// 通过Proxy创建代理对象
Hello hello = (Hello) Proxy.newProxyInstance(
Hello.class.getClassLoader(), // 传入接口类ClassLoader
new Class[] { Hello.class }, // 传入要实现的接口数组
handler); // 传入处理调用方法的InvocationHandler

// 代理对象调用方法:调用handler的invoke方法(反射调用被代理对象的方法)
hello.morning("Bob");
}
}

interface Hello {
void morning(String name);
}

注解 Annotation

  • 注解是放在Java源码的类、方法、字段、参数前的一种特殊“注释”:用作标注的元数据
  • 自定义注解
    • 使用@interface定义注解
    • 添加参数以及default默认值,最常用参数为value
    • 使用元注解配置注解,Target指定应用范围,Retention指定生命周期
1
2
3
4
5
6
7
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Report {
int type() default 0;
String level() default "info";
String value() default "";
}
  • 注解按生命周期分有三类

    • SOURCE:在编译期被丢弃,如@Override、@SuppressWarnings
    • CLASS:仅保存在class文件中,加载结束后并不会存在于内存中
    • RUNTIME:加载进JVM,并且在运行期可以被程序读取
  • 使用反射API读取注解信息

  • 添加自定义注解本身对程序逻辑没有任何影响,需要编写代码来使用注解,比如检查字段规则

泛型

IO 流

多线程

-------- 本文结束 感谢阅读 --------