java基本介绍: java可以简单理解成为编程语言或者开发工具。最终目的是编写用于直接在机器上运行的程序。可跨平台运行(虚拟机的作用) java运行原理:Java源程序经过编译器编译后变成字节码,字节码由虚拟机解释执行,虚拟机将每一条要执行的字节码送给解释器,解释器将其翻译成特定机器上的机器码,然后在特定的机器上运行。 类和对象类是java中最基础的组成单元 面向过程的编程:通过一个函数完成一件事,不会留下任何痕迹,是一次性的。 面向对象编程:时间完成后会将实体中对象抽象出来(类的概念)实体对象是可重复利用的。 类是一群对象的模板,对象是类的实现。
类包含的基本内容:属性和方法。 数据类型标识符、关键字
标识符包括类名、方法名、变量名等。 标识符命名规则: · 只能包含数字、字母(大小写,Unicode字符)、下划线 _、美元符$ · 不能以数字开头 · 不是关键字 数据类型 数值型:
整数型:byte\short\int\long(int double使用较多)
浮点型:float\double 字符型:
char
boolean
在基本数据类型中可以进行类型之间的强制转化。精度低的转化为高的没有问题。精度高的转为低时会出现精度缺失或溢出。 变量变量声明语法:
数据类型 变量名
示例: int a · 1 变量赋值:
变量名 = 值;
示例: a = 1; · 1 简写: int a = 1; · 1 变量生命周期是在{}里。 直接量直接量是直接通过源代码指定值。
例如: int a = 1; · 1 数字1就是直接量
java可定义的直接量包括:基本数据类型,字符串类型。null. 流程控制顺序结构
自上而下的运行过程 判断(分支选择)结构 包括if结构、switch结构
if结构: if (logic expression) { statement; } · 1 · 2 · 3 if (logic expression) { statement; } else { statement; } · 1 · 2 · 3 · 4 · 5 if (logic expression) { statement; } else if (logic expression) { statement; } else { statement; } · 1 · 2 · 3 · 4 · 5 · 6 · 7 switch结构(运用较少): switch (expression) { case condition1 : { statement; break; } case condition2 : { statement; break; } default : { statement; break; }
} · 1 · 2 · 3 · 4 · 5 · 6 · 7 · 8 · 9 · 10 · 11 · 12 · 13 · 14 · 15 在switch结构中要使用break关键字跳出 循环结构
在循环语句满足条件下重复执行某段代码
循环语句包括: 初始化语句:一条或多条语句用于完成初始化
循环条件:决定是否继续执行循环体
循环体:条件允许,循环体反复执行
迭代语句:控制循环 while结构 语法: (init_statement);while (test_expression) { body_statement; [iteration_statement]; } · 1 · 2 · 3 · 4 · 5 do-while结构
语法: (init_statement);do { body_statement; [iteration_statement]; } whi · 1 · 2 · 3 · 4 · 5 区别于while结构do-while结构至少会执行一次 for循环
语法: for ([init_statement]; test_expression; [iteration_statement]) { body_statement; } · 1 · 2 · 3 控制循环结构: break:用于跳出整个循环
continue:用于跳出本次循环,条件符合循环还会继续 数组结构定义语法 type[] 变量名; // 建议用这种命名type 变量名[]; · 1 · 2 数组的初始化
静态初始化:显式的指定每个数组元素的值,由系统来决定数组的大小。 · 列表内容 · 动态初始化:只需要指定数组的长度,通过程序动态的给每个元素赋值。 静态初始化
语法: type[] arrayName = {element1, element2,....}; type[] arrayName = new type[]{element1, element2,...}; 示例:int[] arrs2; arrs2 = new int[]{1, 2 ,3 ,4};int[] arrs = {1, 2, 3, 4}; · 1 · 2 · 3 · 4 · 5 · 6 动态初始化
语法: type[] arrayName = new type[length]; · 1 foreach 遍历数组 for (type element : array | collections) { element... } · 1 · 2 · 3 面向对象编程类和对象
类: 是一种自定义的数据类型。有时把这种数据类型也叫做「类类型」或者「引用数据类型」。「引用」就是内存地址的意思。 对象:
通过类创建的变量,或者叫类的实体。
类是一群对象的特征母版,对象是类的具体实例。
类是一群对象的抽象。 类的定义 类所具备的最基本要素:(静态)属性、(动态)方法。
类的三大部件:成员变量、方法、构造器
语法: [修饰符] class 类名 { // 成员变量 [修饰符] 数据类型 成员变量1; [修饰符] 数据类型 成员变量2; ...
// 方法 [修饰符] 返回值 方法名1([参数列表]) { 方法体语句; } [修饰符] 返回值 方法名2([参数列表]) { 方法体语句; } ...
// 构造器:创建对象用的方法 [修饰符] 类名([参数列表1]) { 方法语句; } [修饰符] 类名([参数列表2]) { 方法语句; }
} · 1 · 2 · 3 · 4 · 5 · 6 · 7 · 8 · 9 · 10 · 11 · 12 · 13 · 14 · 15 · 16 · 17 · 18 · 19 · 20 · 21 · 22 · 23 · 24 构造器
语法: [修饰符] 类名([参数列表]) {} · 1 成员变量
语法 [修饰符] 数据类型 成员变量名 [= 默认值]; · 1 方法
语法: [修饰符] 方法的返回值数据类型 方法名(形参列表) { 方法体语句;} · 1 · 2 · 3 static 关键字 用于修饰成员变量和方法,用 static 修饰的成员变量后者方法是属于 类 的,而不属于该类的实例(对象)。通常把 static 修饰的成员变量称为「类变量、静态变量」,方法称为「类方法、静态方法」
静态的成员是不能访问非静态成员的;
静态成员之间是可以互相访问的。 使用一个对象的过程
定义类
构建和使用对象
语法: 类类型 对象名 = new 构造器方法(); · 1 在内存中的执行过程简介: 1、在栈内存中,会存储对象名,在没有执行构造器创建对象并赋值时,此时对象名对应的值为 null;
2、通过 new 关键字调用类的构造器在堆内存中分配了一块对象区域;
3、通过赋值运算符 = ,将堆内存中的对象地址赋给栈内存中的变量名;
4、例如再次给对象的属性赋值:通过栈内存定位到对象在堆内存中的地址,找到相应的成员变量,进行赋值操作。
this 关键字 Java 中使用 this 关键字,指向调用该方法的对象。根据 this 所在的位置,大致分为两种:
出现在构造器中:引用该构造器正在初始化的对象;
普通方法中:调用该方法的对象。
this 用于在类定义中,获取当前对象的属性,或者调用当前对象的方法。 用 static 修饰的方法中是不能使用 this 关键字的。 方法定义的语法 [修饰符] 返回值类型 方法名(形参列表) { 方法体 } · 1 · 2 · 3 方法中参数传递的机制 参数的传递都是「值传递」,在调用方法的时候,参数会被创造出一个副本,原本的值是不会改变的。
基本数据类型,也称为「值类型」。 public class Demo11 { void fun1(int i, int j) { i = i + 5; j = j + 5; System.out.println("fun1-i:" + i); System.out.println("fun1-j:" + j); }
void fun1(P p) { p.i = p.i + 5; p.j = p.j + 5; System.out.println("fun1-p-i:" + p.i); System.out.println("fun1-p-j:" + p.j); }
public static void main(String[] args) { Demo11 demo11 = new Demo11(); int i = 10; int j = 20; demo11.fun1(i, j); System.out.println("main-i:" + i); System.out.println("main-j:" + j); System.out.println("===================="); P p = new P(); p.i = 10; p.j = 20; demo11.fun1(p); System.out.println("main-p-i:" + p.i); System.out.println("main-p-j:" + p.j);
} }
class P { int i; int j; } 输出:
fun1-i:15 fun1-j:25 main-i:10 main-j:20 ==================== fun1-p-i:15 fun1-p-j:25 main-p-i:15 main-p-j:25 · 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 · 40 · 41 · 42 · 43 · 44 · 45 · 46 · 47 · 48 熟知理解上述代码 变量
根据变量定义所在位置的不同,可以定义:
成员变量:在类中定义的变量,用 static 修饰的为类变量,非 static 修饰的为实例变量。
访问变量的语法: 类.成员变量 实例(对象).成员变量 · 1 · 2 局部变量
局部变量按照定义的位置分为:
在方法内部定义的变量;
在代码块中定义的变量,比如有循环体内部、判断体内部;
形式参数:在方法定义的参数列表中定义的变量;
局部变量生命周期:从定义变量的位置开始,到定义位置所在花括号的结束位置结束。
要注意一般在 for 循环中我们的初始化条件里面定义的变量,其生命周期在循环体内。 隐藏和封装封装
封装是面向对象编程的三大特性之一。
封装目的: 隐藏类方法实现的细节;
让使用者只能通过预先定义的方法来访问数据,从而可以在方法中加入一些控制逻辑,限制对成员变量的不合理访问。
简单的理解就是把成员变量隐藏起来,暴露方法来提供成员的修改和访问 Getter 和 Setter 把属性定义为 private 类型,即私有,向外部暴露其 get 和 set 方法。 访问控制修饰符 访问控制修饰符能修饰的对象包括:成员变量、方法、构造器 深入构造器构造器的最大用处就是创建对象。 如果在类定义中没有显式的定义一个构造器,则编译器在编译源文件时,会创建一个没有参数、没有方法体执行语句的空的构造器。
如果显式的定义了一个构造器,则上述的空的构造器则不会存在。
在调用构造器创建对象的时候,系统会为每个对象的实例变量设置默认值 构造器重载 如果需要在构造器中调用另外一个构造器,可以使用 this(params);
在构造器中调用构造器,必须把this(params)放在有效的执行语句第一行,而且不允许出现两条this(params)语句。 类的继承继承是面向对象的三大特性之一,也是实现软件复用的重要手段。 Java中是单继承,每个子类只有一个直接父类。有的时候把父类也成为基类或者超类。 继承的特点
子类能继承父类的方法 重写父类的方法
在子类中包含与父类同方法签名的现象称为「方法重写(Override)」,有时也称为方法覆盖。我们可以说子类重写了父类的方法,也可以说子类覆盖了父类的方法。
返回值和访问控制修饰符可以不一样,但是要符合“两同两小一大原则”
作为两同就是方法名和方法的参数列表相同
两小:子类的返回值类型和抛出的异常类要比父类的返回值类型和抛出的异常类更小或者相等。这里说的返回值类型小值得的是子类和父类的关系。
一大:子类的访问权限要比父类的访问权限要大或者相等
super限定
super的使用和this的使用很相似。
如果需要在子类中调用父类被覆盖的方法,可以使用super关键字。
同样也可以通过super.fun()调用没有被覆盖的方法,但是这样写没有什么特别的意义,因为本身在子类中就可以直接调用,无需使用super关键字。 子类能够继承父类的信息包括: 没有使用private修饰符修饰的成员变量和方法,子类都能够继承
子类重写了父类的方法,则父类的方法会被隐藏,隐藏的方法或者成员变量可以通过super关键字进行访问
引入super关键字的原因是可以访问被隐藏的成员变量和属性,而且super只能在子类的方法定义中使用。 调用父类的构造器 在子类的构造器中,无论如何在第一行语句中都会调用一次父类的构造器。
如果没有显式的调用,那么会调用父类的没有参数的构造器,如果父类没有定义空参数的构造器,则此时会无法编译。 super()必须出现在第一行,而且只能有一个。
this和super在同一构造器中只可能出现一次。 多态ava引用类型变量有两种类型:一种是编译时的类型,一种是运行时的类型。
编译的类型是由声明变量的时候决定的。
运行时类型由实际赋给该变量的对象决定。
如果运行时的类型和编译时的类型不一致就会出现所谓的多态
引用类型的强制类型转换
强制类型转换是把大的类型转换为小的类型。
在我们的引用数据里,大的类型是父类,小的类型是子类。
只可能发生在子类和父类的关系中 instanceof运算符 instance运算符的前一个操作数一般是引用数据类型变量,后一个操作数是类名(接口),它是用于判断前面的对象是否是后面的类、或者其子类。如果是的话,返回true。 包装类在Java中,基本数据类型本身不是对象,但是为了面向对象设计语言的规范使用,Java对8大基本数据类型进行了包装,提高了相应的构造器、方法以供使用。 包装类中一般会提供两种构造器用于构建对象 使用基本数据类型的参数; 使用字符串类型的参数:对于此类参数,在实际创建对象的时候要注意输入的值要满足条件; 从基本数据转成引用数据的方法: 从构造器创建
自动装箱创建 final 修饰符final 可以修饰在类、成员变量、方法
如果修饰类:则该类不会被继承(一般在开发中很少使用);
如果修饰成员变量:一旦给成员变量赋值后就不允许修改其值,一般用在对常量的定义中。
如果修饰方法: 方法的重载和重写 方法签名:只包含了方法名和参数列表
重写:发生在父类和子类之间,方法签名必须是一样的
重载:发生在本类中,方法名一样,但是参数列表不一样,重载可以是构造器的重载,也可以是方法的重载。 抽象类抽象方法和抽象类
抽象方法和抽象类都是使用 abstract 修饰的 如果在一个类中定义了抽象方法,那么这个类就是抽象类;
抽象类是无法实例化的,只能作为父类被继承使用;
抽象类的构造器只能用于被实现的子类的构造器调用。 抽象类的作用 抽象类一般只是定义需要使用的方法,把不能实现的部分抽象成抽象方法,留给子类去实现。 父类中可以有实现的方法,但是子类也是可以对已经实现的方法进行改造的(override),但是如果在子类中还需要调用父类的实现方法,可以使用 super 关键字。 接口 如果在一个类中,一个实现的方法都没有,或者都是抽象方法,那么,这样的类,成为接口。
接口定义使用 interface 定义
语法: [修饰符] interface 接口名 extends 父接口1, 父接口2... { 0-N 个常量; 0-N个抽象方法; } · 1 · 2 · 3 · 4 接口的继承 接口的继承和类的继承不一样,接口支撑多继承,使用 extends 关键字,之间用逗号隔开,继承的内容包含了,常量和方法 接口的使用 接口是抽象类一样,是不能被实例化的,但是接口可以用于声明引用类型的变量,当使用接口来声明变量时,该变量的运行时类型必须是该接口的实现类。 接口和抽象类
相同点:
都不能被实例化,位于继承树的顶端,是用于被其他类继承或者实现的;
都可以包含抽象方法,子类都必须要实现抽象方法;
在实际的开发中,都是接口先行,一般都是先定义接口,然后开发人员实现接口,完成具体方法的实现。 抽象类是个半成品,可以作为一个模板去使用。 不同点:
抽象类中可以定义普通方法,但是接口中都是抽象方法和静态变量;
在抽象类是可以定义静态方法的,接口中不能定义静态方法的;
在抽象中可以定义构造器的,但是在接口中是不存在构造器这个概念的;
一个类最多只能有一个直接的父类或者抽象类,但是可以有多个接口的实现。 集合框架在集合框架中,主要分为 Collection 和 Map 两大接口。
在 Collection 中又分为 List (有序集合) 和 Set (无序集合)。List 和 Set 都是接口。
Map 存储的 Key-Value 结构。
Collection
List
是实际开发中用的最多的一种数据结构,存储的单个元素,使用泛型去强制约束 List 中存放的是一致的数据类型
插入元素 add() · 1 遍历元素
通过元素索引下标方式 for 循环
通过 foreach 循环
通过迭代器 Iterator
删除元素
使用迭代器遍历集合,调用 Iterator.remove() 方法删除。
Map
类似的可以理解给集合元素中的值定义了一个 Key 键(遍历),之后可以通过相关的方法快速的定位到具体的 Value 中。 获取某个 key 的 value
Value get(Key) 遍历 Map 结构
获取 Map 的 Key 集合,通过遍历 Key 集合,获取 Value 值。
获取 key 集合:map.keySet();
遍历 Key 集合:iterator;
获取 Value 值:get(key); 常用类Object
toString() :直接打印对象调用该方法,一般在类中重写(override)。 默认的 toString() 是打印类全名+hashcode
hashCode():返回该对象的哈希码值,内存地址。 String
构建字符串的方式 String s1 = new String("hello"); char[] cs = {'h','e','l','l','o'};String s2 = new String(cs);String s3 = "hello"; // 最常用 · 1 · 2 · 3 · 4 常用的一些方法 charAtreplacesplit indexOf substringcontains · 1 · 2 · 3 · 4 · 5 · 6 示例: public class Demo1 { public static void main(String[] args) { // 字符串的构建方式
String s1 = new String("hello");
char[] cs = { 'h', 'e', 'l', 'l', 'o' }; String s2 = new String(cs);
String s3 = "hello"; // 最常用
System.out.println(s1); System.out.println(s2); System.out.println(s3);
System.out.println(s3.charAt(1));
String s4 = s3.concat(",world!");
System.out.println(s4);
System.out.println(s4.contains("world1"));
String s5 = "d:/a/index.js"; System.out.println(s5.endsWith(".js"));
// 对于字符串的比较操作,一般的场景都是比较字符串的内容是否一致 String s6 = "tom"; String s7 = new String("tom"); System.out.println(s6 == s7); // false System.out.println(s6.equals(s7)); // true
String s8 = "hello,world!"; System.out.println(s8.indexOf("world")); // 6
String s9 = "a1a2a3b4a5"; System.out.println(s9.indexOf("a")); // 0 System.out.println(s9.indexOf("a", 1)); // 2
List<Integer> indexs = getIndexsOfStr("1a22a3444a4b", 'a'); for (Integer index : indexs) { System.out.print(index + "\t"); }
// 打印文件的后缀 String s10 = "d:/a/index.js"; int s10_1 = s10.lastIndexOf(".") + 1; String s10_2 = s10.substring(s10_1); System.out.println(s10_2);
String s11 = "abcabcabc"; System.out.println(s11.replace("a", "A")); System.out.println(s11.replaceFirst("a", "A"));
String s12 = "a-b-c-d-e-f"; String[] s12s = s12.split("-"); for (String s : s12s) { System.out.println(s); }
String s13 = "20171108001"; System.out.println(s13.startsWith("20171108"));
System.out.println(s12.toUpperCase());
String s14 = " hello,wolrd! "; String s15 = s14.trim(); System.out.println("#"+s14+"#"); System.out.println("#"+s15+"#");
}
// 传入一个字符串,输出某个字符在传入字符串中的所有位置
public static List<Integer> getIndexsOfStr(String src, char c) { List<Integer> rs = new ArrayList<Integer>();
if (null != src) { char[] cs = src.toCharArray();
for (int i = 0; i < cs.length; i++) { if (cs == c) { rs.add(i); } } }
return rs; }
// 传入一个字符串,输出某个字符在传入字符串中的所有位置
public static List<Integer> getIndexsOfStr(String src, String c) { List<Integer> rs = new ArrayList<Integer>();
if (null != src) { }
return rs; }
} · 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 · 40 · 41 · 42 · 43 · 44 · 45 · 46 · 47 · 48 · 49 · 50 · 51 · 52 · 53 · 54 · 55 · 56 · 57 · 58 · 59 · 60 · 61 · 62 · 63 · 64 · 65 · 66 · 67 · 68 · 69 · 70 · 71 · 72 · 73 · 74 · 75 · 76 · 77 · 78 · 79 · 80 · 81 · 82 · 83 · 84 · 85 · 86 · 87 · 88 · 89 · 90 · 91 · 92 · 93 · 94 · 95 · 96 · 97 · 98 · 99 · 100 · 101 · 102 · 103 · 104 **StringBuffer
在进行大数据的字符串拼接时使用 StringBuffer** public class Demo3 { public static void main(String[] args) {
Date d11 = new Date(); String s = ""; for (int i = 0; i < 100000; i++) { s += 1; } Date d22 = new Date(); System.out.println(d22.getTime() - d11.getTime()); // 3418
Date d1 = new Date(); StringBuffer sb = new StringBuffer(""); for (int i = 0; i < 100000; i++) { sb.append(i); } Date d2 = new Date(); System.out.println(d2.getTime() - d1.getTime()); // 16 } } 日期 java.util.Date 和 Calendar Date 和 SimpleDateFormat 的运用 public class Demo4 { public static void main(String[] args) throws ParseException { // 构建当前服务器的时间对象 Date now = new Date(); System.out.println(now);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS"); System.out.println(sdf.format(now)); // 格式化的目的是用于显示
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss"); String dateStr = "2017/10/09 13:04:30"; Date now2 = sdf2.parse(dateStr); // 通过一个字符串解析成日期对象 System.out.println(now2.getYear()+1900);
} } · 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 · 40 · 41 Calendar 是更加先进的日期处理类
如果只是简单的对日期进行输入,用 Date 就可以了,但是如果要对日期进行复杂的运算,就要使用 Calendar 类,Calendar 和 Date 是可以互相转化的。
Calendar 和 Date 的转换
使用 Calendar 进行复杂的日期运算
Calendar 只是个工具,具体的日期还是要使用 Date 对象 public class Demo5 { public static void main(String[] args) throws ParseException { String dateStr = "2017/11/11"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); Date date = sdf.parse(dateStr);
Calendar rightNow = Calendar.getInstance(); rightNow.setTime(date);
rightNow.add(Calendar.DAY_OF_MONTH, 30); rightNow.add(Calendar.MONTH, 1);
System.out.println(rightNow.get(Calendar.DAY_OF_MONTH)); System.out.println(rightNow.get(Calendar.MONTH));
rightNow.set(Calendar.YEAR, 2019);
rightNow.add(Calendar.DAY_OF_MONTH, -1);
System.out.println(sdf.format(rightNow.getTime()));
} } · 1 · 2 · 3 · 4 · 5 · 6 · 7 · 8 · 9 · 10 · 11 · 12 · 13 · 14 · 15 · 16 · 17 · 18 · 19 · 20 · 21 · 22 · 23 异常处理如果不处理异常,一旦在出现异常的地方,程序就会被「异常指令流」直接终止,不再往下运行。
处理异常
使用 try catch
在 try catch 结构中,catch 是可以省略的,也可以多异常的捕获,但是出现多异常的时候,父类异常只能出现在最下面。 在实际的开发中,一般最简单的方式就是使用一个 Exception 直接处理。 finally 无论是否出现异常都会被执行,特别要注意的是,如果没有写 catch ,那么 finally 是会被执行的,但是中断后的语句是不会被执行的。 throws 在方法定义的后面显式的声明方法是有异常的,调用该方法的程序是要显式的处理异常,后者也可以再次抛出。
throw 自定义的创建一个异常对象。在一般的异常发生时候,虚拟机会动态的创建一个「系统异常」抛出,和自定义使用 throw 抛出是一个概念。 异常堆栈信息
异常类
异常提示信息:getMessage()
异常所在的代码位置:自下而上是异常出现的代码所在方法的调用顺序的先后。 单例模式在实际的开发中,绝对部分的服务性质的类都会设计成单例模式 所谓的单例模式,就是类只有一个对象,外部要使用该类的对象,通过调用一个类方法实现。 /** * 饱汉式单例模式 * @author lzq31 * */public class Service2 {
private static Service2 service = new Service2();
private Service2() {
}
public static Service2 getInstance() { return service; } }/** * 饿汉式单例模式 * @author lzq31 * */public class Service {
private static Service service;
private Service() {
}
public static Service getInstance() { if (null == service) { service = new Service(); } return service; } }
|