文章目录
Java
1.易错点
1.1 数组的声明和创建
datatype[] arrayname = {8,4,20,100,23,34,12,88,66,9};
datatype[] arrayname=new int[size];
1.2 java中不存在封装好的swap函数
java实现swap函数很麻烦,不如直接三步交换赋值。
2.基础语法
2.1数组
2.11数组的声明和创建
datatype[] arrayname = {8,4,20,100,23,34,12,88,66,9};
datatype[] arrayname=new int[size];
2.12数组在函数中的参数传递
printArray(array);
public static void printArray(int[] array) {
函数体
}
2.13数组的输出
2.131一维数组
low版输出:
for(int i=0;i<array.length;i++){
System.out.print(array[i]+" ");
}
输出结果:
4 5 6 11 19 21
优美版输出:
System.out.println(Arrays.toString(array));
输出结果:
[4, 5, 6, 11, 19, 21]
2.132多维数组
Arrays.deepToString();
2.14数组的复制
low版:通过for循环遍历数组赋值。
high版:赋值函数。
System.arraycopy(Object src,int srcPos,Object dest,int destPos,int length);
在该方法中,src为源数组,srcPos为数组复制的起始位置,dest为目标数组,destPos为目标数组复制的起始位置,length为数组复制的长度
2.2 Scanner类
2.21 创建Scanner类对象的基本语法
Scanner 类y用来获取用户的输入。
Scanner sc = ``new` `Scanner(System.in);
2.22 next 方法
调用sc的对象的next方法,返回整型浮点型数据。
int character = sc.nextInt();
float character = sc.nextFloat();
double character = sc.nextDouble();
char character = sc.next();
String character = sc.next();
2.3Static关键字
2.31静态变量
小结:
1) static 修饰符修饰的属性(成员变量)称为静态变量,也可以称为类变量。
2)可以直接通过类名访问:类名.静态变量名
3)静态变量可以被类的所有实例共享,因此静态变量可以作为实例之间的共享数据,增加实例之间的交互性。
4)在内存中只有一个拷贝
5)类内部,可在任何方法内直接访问静态变量
6)其他类中,可以直接通过类名访问
7)静态变量也叫类变量,它属于一个类,而不是这个类的对象。
8)由于静态变量属于一个类,所以不能通过对象引用来访问,而应该直接通过类名来访问;
9) 不需要初始化类就可以访问静态变量。
public class WriterDemo {
public static void main(String[] args) {
System.out.println(Writer.countOfWriters); // 输出 0
}
}
例子:
public class Writer {
private String name;
private int age;
public static int countOfWriters;
public Writer(String name, int age) {
this.name = name;
this.age = age;
countOfWriters++;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
其中,countOfWriters 被称为静态变量,它有别于 name 和 age 这两个成员变量,因为它前面多了一个修饰符 static
。
这意味着无论这个类被初始化多少次,静态变量的值都会在所有类的对象中共享。
Writer w1 = new Writer("沉默王二",18);
Writer w2 = new Writer("沉默王三",16);
System.out.println(Writer.countOfWriters);
按照上面的逻辑,可以推理出,countOfWriters 的值此时应该为 2 而不是 1。
从内存的角度来看,静态变量将会存储在 Java 虚拟机中一个名叫“Metaspace”(元空间,Java 8 之后)的特定池中。
静态变量和成员变量有着很大的不同,成员变量的值属于某个对象,不同的对象之间,值是不共享的;但静态变量不是的,它可以用来统计对象的数量,因为它是共享的。就像上面例子中的 countOfWriters,创建一个对象的时候,它的值为 1,创建两个对象的时候,它的值就为 2。
#### 2.32静态方法
##### 小结:
1)Java 中的静态方法在编译时解析,因为静态方法不能被重写(方法重写发生在运行时阶段,为了多态)。
2)抽象方法不能是静态的。
3)静态方法不能使用 this 和 super 关键字。
4)成员方法可以直接访问其他成员方法和成员变量。
5)成员方法也可以直接方问静态方法和静态变量。
6)静态方法可以访问所有其他静态方法和静态变量。
7)静态方法无法直接访问成员方法和成员变量。
8)静态方法也叫类方法,它和静态变量类似,属于一个类,而不是这个类的对象。
例子:
public static void setCountOfWriters(int countOfWriters) {
Writer.countOfWriters = countOfWriters;
}
setCountOfWriters()
就是一个静态方法,它由 static 关键字修饰。
如果你用过 java.lang.Math 类或者 Apache 的一些工具类(比如说 StringUtils)的话,对静态方法一定不会感动陌生。
Math 类的几乎所有方法都是静态的,可以直接通过类名来调用,不需要创建类的对象。
2.33静态代码块 (存疑,未实践)
小结:
1)static修饰的代码块称为静态代码块
2)当Java虚拟机加载类时,就会执行该代码块
3)什么时候会用到静态代码块呢?
a.将一些只需要进行一次的初始化操作都放在 static 代码块中进行
b.用于初始化类,为类的静态变量赋初始值
注意
4) 可以置于类中的任何地方,类中可以有多个静态初始化块。
5) 如果有多个静态块,按顺序加载
6) 每个静态代码块只会被执行一次
2.34静态内部类
2.4继承
2.40对象引用
父类引用指向子类对象,子类引用不能指向父类对象。
第 1 个例子:
Father f1 = new Son(); // 这就叫 upcasting (向上转型)
// 现在 f1 引用指向一个Son对象
Son s1 = (Son)f1; // 这就叫 downcasting (向下转型)
// 现在f1 还是指向 Son对象
第 2 个例子:
Father f2 = new Father();
Son s2 = (Son)f2; // 出错,子类引用不能指向父类对象
2.41向上转型
概念:
把子类对象直接赋给父类引用叫upcasting向上转型,向上转型不用强制转换。
通俗地讲即是将子类对象转为父类对象。此处父类对象可以是接口。
如:
Father f1 = new Son();
例子:
Staff sale =new SalesStaff(10,100000);
sale.printpayslip();
1)需要注意的是向上转型时 b 会遗失除与父类对象共有的其他方法。如本例中的 fly 方法不再为 b 所有。
即只能调用子类与父类共有的方法。
2)若直接通过实例化对象构造方法传参则可用向上转型。
2.42向下转型
概念:
把指向子类对象的父类引用赋给子类引用叫向下转型(downcasting),要强制转换,如:
f1 就是一个指向子类对象的父类引用。把f1赋给子类引用 s1 即 **Son s1 = (Son)f1;**其中 f1 前面的(Son)必须加上,进行强制转换。
通俗来讲,向下转型与向上转型相反,即是把父类对象转为子类对象。
例子:
Staff sale =new SalesStaff();//向下转型需先向上转型
SalesStaff sales=(SalesStaff) sale;//向下转型
sales.setYears(10);
sales.setTotalsales(100000);
sales.printpayslip();
1)当子类需要创建自己独有的方法时,向上转型则不适用。
2)向上转型时 b会遗失除与父类对象共有的其他方法;可以用向下转型在重新转回,这个和向上转型的作用要结合理解。
- 向下转型可以直接调用子类对象的独有方法。
2.43 多继承和多重继承
Java中只存在多重继承,不存在多继承。
多重继承:步兵是士兵,士兵也是人类。
多继承:一个子类可能有两个父亲。
2.5多态
2.5.1多态存在的三个必要条件
- 继承
- 重写
- 父类引用指向子类对象
不要弄混淆了,父类的方法在重写后会被子类覆盖,当需要在子类中调用父类的被重写方法时,要使用super关键字。
2.6抽象类和接口
2.61抽象类
2.611抽象类的定义格式
2.612抽象方法
特征
1)抽象方法没有方法体,不需要花括号。
2)抽象方法必须存在于抽象类中。
3)子类继承父类时,必须重写父类所有的抽象方法。
2.613抽象类的特征
抽象类的特征
1. 抽象类不能被实例化,也就是不能用new关键字去产生对象。
2. 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象的。
3. 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。
4. 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。
5. 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。
2.62接口
2.621接口的定义
2.622接口的实现
注意
1)当类实现接口的时候,类要实现接口中所有的抽象方法。否则,类必须声明为抽象的类。
2)允许一个类实现多个接口,从而也解决了Java类单一继承问题。
2.623接口的特征
1)在JDK1.8之前,接口中的方法都必须是抽象的,并且方法不能包会方法体。在调用抽象方法时,必须通过接口的实现类的对象才能调用实现方法。
2)从JDK1.8开始,接口中的方法除了包含抽象方法外,还包含默认方法和静态方法,默认方法和静态方法都可以有方法体,并且静态方法可以直接通过“接口.方法名”来调用。
3)当一个类实现接口时,需要实现接口中的所有抽象方法。如果不想实现接口中的抽象方法,则需要将该类声明为抽象类。
4)一个类可以通过implements 关键字同时实现多个接口,被实现的多个接口之间要用英文逗号(,)隔开。
5)一个类在继承一个类的同时还可以实现接口,此时,extends 关键字必須位于implements 关键字之前。具体示例如下:Class A extends B implements C //先继承类,再实现接口。
2.624使用接口的目的
解决Java无法使用多继承的问题
制定标准的(制定规范)
2.63抽象类和接口的异同
2.631相同点
1)都可以被继承/实现
2)都不能被实例化
3)派生类/实现类必须实现未实现的抽象方法
2.632不同点
1)抽象类中可以定义构造方法,接口中不能定义构造方法。
2)抽象类可以有抽象方法和具体方法,接口中的方法全部都是抽象方法(JDK1.8之前)。
3)从JDK1.8开始,还包含默认方法和静态方法,默认方法和静态方法都可以有方法体。
4)抽象类中的成员可以是 private、默认、protected、public,接口中的成员全都是public的。
5)抽象类中可以定义成员变量,接口中定义的成员变量实际上都是常量。
6)抽象类中可以包含静态方法, 接口中不能有静态方法(JDK1.8之前)。
7)一个类只能继承一个抽象类,一个类可以实现多个接口。
2.7String与Array
2.71字符串的输入
String id=sc.nextLine();
2.72字符串输入的应用场景
当输入的字符位数无法确定时,可以先输入字符串然后再转字符数组,这样可以避免数组创建时必须声明数组的长度。
例如输入身份证号码(身份证号码为18位或19位,长度不固定)
2.73字符串与字符数组的转化。
字符串转字符数组
String id=sc.nextLine();
char []idnum=id.toCharArray();
字符数组转字符串
char[] arr={'a','b','c'};
String string =String.copyValueOf(arr);
System.out.println(string); //abc
2.74字符串与整型变量的转化
字符串到整型变量
int i = Integer.valueOf(str).intValue();
整型变量到字符串
String str = Integer.toString(i);
2.75创建新字符串方式的区别
String str1 是声明一个字符串常量不开辟内存空间。
String str2=new String(“ambow”)需要开辟内存空间。
2.8正则表达式
2.81身份证号码正则表达式
String id=sc.nextLine();
String pattern = "(^\\d{17}$)|(^\\d{18}$)|(^\\d{17}(\\d|X|x)$)";//身份证的正则表达式
Pattern r = Pattern.compile(pattern);//编译正则表达式
Matcher m = r.matcher(id);//编译给定正则表达式并尝试将给定输入与其匹配。
System.out.println(m.matches());
正则表达式的使用需要配合Pattern和Matcher类使用。
Pattern 类:
pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。
Matcher 类:
Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
3.常用API
3.1Math
3.11 Math.random
Math是数学类,random()是Math类中的一个方法,random本身只产生(0~1)之间小数。
int random = (int)(Math.random()*10); //产生随机数
random()*10 意思是产生0~10之间的小数 ,int(random()10)的意思是强制取整,把小数部分去掉只去整数部分,所以 就变成了 产生0~9之间的整数。
(char) ('0' + Math.random() * 10);
意为将随机数转化成字符。
3.2Random
3.21Random.nextInt(bound)
该方法的作用是生成一个随机的int值,该值介于[0,bound)的区间,也就是0到bound之间的随机int值,包含0而不包含bound。
(char) ('0' + r.nextInt(10));
意为将0到9的随机int数转化为字符
例子:生成一个十五位数字的字符串
int len = 15;
char[] pwd = new char[len];
int i = 0;
Random r = new Random();
while(i < len) {
pwd[i] = (char) ('0' + r.nextInt(10));
i ++;
}
System.out.println(pwd);
3.3Pattern类和Matcher类
Pattern 类:
pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。
Matcher 类:
Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
3.4集合框架
3.41体系图
3.42List集合
3.420List概念
1)List 集合允许使用重复元素,可以通过索引来访问指定位置的集合元素。
2)List 集合默认按元素的添加顺序设置元素的索引。
3)第一个添加到 List 集合中的元素的索引为 0,第二个为 1,依此类推。
3.421常用实现类
1.ArrayList
ArrayList实现了长度可变的数组,在内存中分配连续的空间。遍历元素和随机访问元素的效率比较高。
2.LinkedList(了解)
LinkedList采用链表存储方式。插入、删除元素时效率比较高。
3.ArrayList 类和 LinkedList 类的区别?
**1)**ArrayList 是基于动态数组数据结构的实现,访问元素速度优于 LinkedList。对于快速访问对象的需求,使用 ArrayList 实现执行效率上会比较好。
**2)**LinkedList 是基于链表数据结构的实现,占用的内存空间比较大,但在批量插入或删除数据时优于 ArrayList。需要频繁向集合中插入和删除元素时,使用 LinkedList 类比 ArrayList 类效果高。
3.422遍历List集合的四种方法
3.4221索引法
根据List集合的索引获得元素对象:get(int i);
例子:
System.out.println("1.索引法:");
for(int i=0;i<arrayList.size();i++){
print((Student) arrayList.get(i));
} //get()方法获取的是Object类型
3.4222增强for循环(foreach语句)
1)增强for循环是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合的。
2)增强for循环通常只进行遍历元素,不要在遍历的过程中对集合元素进行增删操作。
例子:
System.out.println('\n'+"2.增强for循环法:");
for (Object ob:arrayList) {
print((Student) ob);
}
3.4223Iterator迭代器法
获取Iterator :Collection 接口的iterator()方法
Iterator的方法
boolean hasNext(): 判断是否存在另一个可访问的元素
Object next(): 返回要访问的下一个元素
例子:
System.out.println('\n'+"3.迭代器法:");
Iterator integer= arrayList.iterator();
while(integer.hasNext()){
print((Student) integer.next());
}
3.4224Lambda表达式
1)Java 8 为 Iterable 接口新增了一个 forEach(Consumer action) 默认方法
2) Collection 集合可直接调用该方法
3)Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
lambda 表达式的语法格式如下:
(parameters) -> expression 或 (parameters) ->{ statements; }
以下是lambda表达式的重要特征:
- **可选类型声明:**不需要声明参数类型,编译器可以统一识别参数值。
- **可选的参数圆括号:**一个参数无需定义圆括号,但多个参数需要定义圆括号。
- **可选的大括号:**如果主体包含了一个语句,就不需要使用大括号。
- **可选的返回关键字:**如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
System.out.println('\n'+"4.Lambda表达式法:");
arrayList.forEach(item->{
print((Student) item);
});
/*
arrayList.forEach(System.out::println);
*/
3.423List接口常用方法
3.43Map集合
3.431概念
Map 是一种键-值对(key-value)集合,Map 集合中的每一个元素都包含一个键(key)对象和一个值(value)对象。用于保存具有映射关系的数据。
3.432常用实现类
3.4321HashMap
1.概念:
HashMap 类按哈希算法来存取键对象
2.特点:
1)HashMap 类按哈希算法来存取键对象
2)不保证顺序
3)允许null值和null键
4)键不允许重复,值可以重复(如果存入了两个相同的键,只保存最后一个存入的键值
5)对非线性安全
3.声明初始化:
Map<key,value> map = new HashMap<key,value>();
//key和value位置要填写key和value的类型。
4.常用方法:
举例:
1)put方法: V put(key ,value);
使用的参数:该方法有两个参数。
- key - 与指定值相关联的键。
- value - 与指定键关联的值。
返回值:当存在这个key的时候,会覆盖掉原来的value并返回oldvalue,也就是旧值。
对返回值的进一步解释:
- 如果没有键映射,则返回NULL。
- 该函数返回与指定键关联的旧值。
- 这个操作不管啥条件都会覆盖旧的。
2)Get()方法: get(key):
使用的参数:
- Key - 其关联值将被返回的键。
返回值:指定键映射到的值,如果此映射不包含键的映射,则为NULL。
返回值进一步阐述:
- 使用get函数,那么应该有先调用put函数对m表进行存储,不然肯定是返回null;
- 由于m表的存储跟put函数有关,在实际工程应用中get返回值是受到put函数影响的。
5.例子:
Country c1 = new Country("1001","中国","东亚");
Map<String,Country> map = new HashMap<String,Country>();
map.put(c1.getcId(),c1);
for (String key : map.keySet()) {
map.get(key).cInformation());}
}
3.44日期相关类
在 Java 中获取当前时间,可以使用 java.util.Date 类和 java.util.Calendar 类完成。其中,Date 类主要封装了系统的日期和时间的信息,Calendar 类则会根据系统的日历来解释 Date 对象。
3.441Date
概念 Date 类表示系统特定的时间戳,可以精确到毫秒。Date 对象表示时间的默认顺序是星期、月、日、小时、分、秒、年。
构造方法:
Date date = new Date();
常用方法:
date.getTime()获取的是从1970年1月1日 00:00:00到现在的时间毫秒数
3.442DateFormat
1.概念
DateFormat 是日期/时间格式化子类的抽象类,它以与语言无关的方式格式化并解析日期或时间。
2.日期/时间格式化子类(SimpleDateFormat类)
1)格式化(日期 -> 文本)
对象.format(Date date) : 将Date对象转换成String
代码演示
2)解析(文本-> 日期)
对象.parse(String source) : 将String转换成Date
代码演示
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DFE7elDj-1611388885421)(C:\Users\清水\Desktop\开发部门项目组\截图\QQ截图20210122091744.png)]
注意
转换时,该String要符合指定格式,否则不能转换
3)日期和时间格式
4)代码演示
DateFormat dateFormat = new SimpleDateFormat("yyyy年-MM月-dd日 HH:mm:ss");
String now = dateFormat.format(date);
System.out.println(now);
3.45Java流(Stream),文件(File)和IO
3.451类层次图
3.452FileOutputStream流
1) FileOutputStream流是指文件字节输出流,专用于输出原始字节流如图像数据等,其继承OutputStream类,拥有输出流的基本特性。
2)创建FileOutputStream流以写入数据到File对象表示的文件。 如果第二个参数为true,则字节将写入文件的末尾而不是开头。
File file = new File("C:\\Users\\清水\\Documents\\专业\\java\\temp.txt");
FileOutputStream fileOutputStream = new FileOutputStream(file);
String str="全世界的无产者联合起来";
fileOutputStream.write(str.getBytes());
write()方法
write(byte[] b)
使用方法write(byte[] b),即向文件写入一个byte数组的内容
write(byte[],off,length)
fileOutputStream.write(bys,0,len);//读取byte数组中从第一个到第len个的字节
3.453FileInputStream流
读取的两种方法,read()和read(byte[] b)
1.read();
从输入流中读取数据的下一个字节,返回0到255范围内的int字节值。如果因为已经到达流末尾而没有可用的字节,则返回-1。在输入数据可用、检测到流末尾或者抛出异常前,此方法一直阻塞。
InputStream.read()这个方法是从流里每次只读取读取一个字节,效率会非常低。 更好的方法是用InputStream.read(byte[] b)或者InputStream.read(byte[] b,int off,int len)方法,一次读取多个字节。
2.read(byte[] b)
从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。以整数形式返回实际读取的字节数。在输入数据可用、检测到文件末尾或者抛出异常前,此方法一直阻塞。如果 b 的长度为 0,则不读取任何字节并返回 0;否则,尝试读取至少一个字节。如果因为流位于文件末尾而没有可用的字节,则返回值 -1;否则,至少读取一个字节并将其存储在 b 中。将读取的第一个字节存储在元素 b[0] 中,下一个存储在 b[1] 中,依次类推。读取的字节数最多等于 b 的长度。设 k 为实际读取的字节数;这些字节将存储在 b[0] 到 b[k-1] 的元素中,不影响 b[k] 到 b[b.length-1] 的元素。
read()方法每次只能读取一个字节,所以也只能读取由ASCII码范围内的一些字符。这些字符主要用于显示现代英语和其他西欧语言。而对于汉字等unicode中的字符则不能正常读取。只能以乱码的形式显示。
FileInputStream fileInputStream = new FileInputStream("C:\Users\清水\Documents\专业\java\test1.png");
int len = 0;//用来接收读出来的字符长度
byte[] bys = new byte[1024];//一般长度设置为1024的整数倍
while(true) {
try {
if (!((len = fileInputStream.read(bys)) != -1)) break;
} catch (IOException e) {
e.printStackTrace();
}//当读到还有字节的时候,写文件输出
try {
fileOutputStream.write(bys,0,len);//读到多少写多少
} catch (IOException e) {
e.printStackTrace();
}
}
fileInputStream.close();
fileOutputStream.close();
少读取一个字节并将其存储在 b 中。将读取的第一个字节存储在元素 b[0] 中,下一个存储在 b[1] 中,依次类推。读取的字节数最多等于 b 的长度。设 k 为实际读取的字节数;这些字节将存储在 b[0] 到 b[k-1] 的元素中,不影响 b[k] 到 b[b.length-1] 的元素。
read()方法每次只能读取一个字节,所以也只能读取由ASCII码范围内的一些字符。这些字符主要用于显示现代英语和其他西欧语言。而对于汉字等unicode中的字符则不能正常读取。只能以乱码的形式显示。
FileInputStream fileInputStream = new FileInputStream("C:\Users\清水\Documents\专业\java\test1.png");
int len = 0;//用来接收读出来的字符长度
byte[] bys = new byte[1024];//一般长度设置为1024的整数倍
while(true) {
try {
if (!((len = fileInputStream.read(bys)) != -1)) break;
} catch (IOException e) {
e.printStackTrace();
}//当读到还有字节的时候,写文件输出
try {
fileOutputStream.write(bys,0,len);//读到多少写多少
} catch (IOException e) {
e.printStackTrace();
}
}
fileInputStream.close();
fileOutputStream.close();