断断续续五个月,总算把Java基础系统学习了一遍,本节主要是对前面学习的一个总结文。由于本人已经工作,深知基础的重要性,即使工作很忙,也还是挤着时间努力输入。有时觉得坚持很难很难,好在自己还是坚持了过来,不过这只是编程路上跨过的小小一步,前路漫漫,吾将持续求索。
此篇文章为Java基础的一个小结束,是我编程之旅的新起点。
时光不负赶路人,星光不负追梦人,加油!!!
本文已收录于[ 专栏 ]
《Java入门》系列
按照下面分类的知识点,形成一张表格以便时时检验自己的基本功。
先举个例子,给定一个业务:Panda飞猪要学会Java并且利用Java语言编程。
面向过程的老师A首先让Panda飞猪第一步看视频做笔记,第二步做题写代码,第三部系统看书写代码来达到Panda飞猪想要的目的。
面向对象的老师B首先让Panda飞猪找所有可以学习Java的工具:书、视频、编程的工具IDEA,接着让Panda飞猪自己利用这些对象达到Panda飞猪想要达到的目的。
可以很明显的看到,面向对象的老师让Panda飞猪找到了对象,但是Panda飞猪还是需要去学习面向过程的老师A的一些方法去真正利用对象达到目的。
面向过程:是一种以过程为中心的编程思想,它是一种基础的顺序的思维方式,面向对象方法的基础实现中也包含面向过程思想。
面向对象:按人们认识客观世界的 系统思维方式,采用基于对象(实体)的概念建立模型,模拟客观世界分析、设计、实现软件的办法。通过面向对象的理念使计算机软件系统能与现实世界中的系统一一对应。
面向对象语言是只一切操作都以对象为基础,它是由面向过程语言发展而来的,但正是它的这个特性使得面向对象语言对底层的操作不是很方便。例如:java语言。
面向过程语言是以过程或函数为基础的,这种语言对底层硬件,内存等操作比较方便,但是写代码和调试维护等会很麻烦。例如:c语言。
总结一下哦,有如下几个方面的不同:
面向对象强调把问题直接映射到对象之间的接口上。面向过程强调的过程的抽象化与模块化,以过程为中心,构造、处理世界。
面向对象,数据与对应的代码封装成一个整体,原则上其他对象不能直接修改其数据,对象的修改只能由自身的完成;面向过程,通过程序处理数据,处理完显示结果,在控制方式上是按照设计调用或返回程序,不能自由导航,各模块之间存在着控制与被控制,调动与被调用的关系。
面向对象方法贯穿于软件生命周期的分析,设计及编码中,是一种平滑过程,即实现的是无缝连接。面向过程,强调分析、设计及编码之间按规则进行,实现的是有缝连接。
名称 | 含义 |
---|---|
类 | class :用来描述某一类对象的共同特征 |
对象 | 具体的事物、实体 |
包 | Package,可以放很多类 |
接口 | 与抽象类相似,是一批类要遵守的规范 interface |
抽象 | abstract,只声明方法不实现方法 |
枚举 | 一组固定的常量组成合法值的类型 |
函数 | 用来实现某个功能的方法 |
常量 | final修饰,值不变的量 |
变量 | 可被多次改变数值的量 |
Java源文件由编译器编译成字节码(ByteCode) ,字节码由java虚拟机(JVM)解释运行。
手动编译Java源代码过程
如下面例子:定义了类、常量、变量、方法
package com.algorithm;
/**
* @Author: qp
* @Time: 2021/10/18 21:57
* @Description
*/
public class DemoPractice {
static final float TEST_PI=3.14f;
final float PI=3.14f;
float testPi =3.14f;
@Override
public String toString() {
return "DemoPractice{" +
"TEST_PI=" + TEST_PI +
", testPi=" + testPi +
'}';
}
}
如下面例子:
package com.algorithm;
import java.util.ArrayList;
/**
* @Author: qp
* @Time: 2021/10/18 21:57
* @Description
*/
public class DemoPractice {
byte aByte = 1;
short aShort = 2;
int anInt = 4;
long aLong = 8;
final float TEST_PI = 3.14f;
float testPi = 3.14f;
double aDouble = 3.24;
char aChar = 'c';
boolean aBoolean=false;
String string="你好";
Integer integer1 = new Integer(1);
}
如下面例子:
public class DemoPractice {
byte aByte = 1;
short aShort = 2;
int anInt = 4;
long aLong = 8;
final float TEST_PI = 3.14f;
float testPi = 3.14f;
double aDouble = 3.24;
char aChar = 'c';
boolean aBoolean = false;
String string = "你好";
ArrayList arrayList = new ArrayList();
private void math() {
int i = aByte + aShort;
i-=aShort;
i*=aByte;
i/=aByte;
long max=(anInt>aLong)?anInt:aLong;
i=1>>2;
}
}
如下面的代码:循环的三种代码实现,选择中嵌套分支结构
public class Demo {
//while循环
private static int sum1(int num, int sum) {
while (num <= 100) {
sum = sum + num;
num++;
}
return sum;
}
//do while循环
private static int sum2(int num, int sum) {
do {
sum = sum + num;
num++;
} while (num <= 100);
return sum;
}
//for循环
private static int sum3(int num, int sum) {
for (int i = 1; i <= 100; i++) {
sum = sum + num;
num++;
}
return sum;
}
public static void main(String[] args) {
int sum = 0;
int num = 1;
Scanner scanner = new Scanner(System.in);
int choice= scanner.nextInt();
switch (choice){
case(1):
System.out.println("第1种求和方式"+sum3(num, sum));
break;
case(2):
System.out.println("第2种求和方式"+sum2(num, sum));
break;
case (3):
System.out.println("第3种求和方式"+sum3(num, sum));
break;
default:
System.out.println("默认求和方式"+sum3(num, sum));
break;
}
}
}
一篇文章读懂封装、继承、多态,接下来,举个例子说明封装、继承、多态;
import java.beans.DesignMode;
import java.util.Scanner;
/**
* Math类中封装了2个求和的方法
*/
class Math {
//while循环
protected int sum1(int num, int sum) {
while (num <= 100) {
sum = sum + num;
num++;
}
return sum;
}
//do while循环
protected int sum2(int num, int sum) {
do {
sum = sum + num;
num++;
} while (num <= 100);
return sum;
}
}
/**
* Demo继承了Math中所有的非private修饰的方法并且可以重写
*/
public class Demo extends Math{
/**
* @param num
* @param sum
* @return 重写了求和方法,编译时多态
*/
@Override
protected int sum1(int num, int sum) {
for (int i = 1; i <= 100; i++) {
sum = sum + num;
num++;
}
return sum;
}
public static void main(String[] args) {
int sum = 0;
int num = 1;
//向上类型转换,运行时的多态
Math math = new Demo();
math.sum1(2,0);
}
}
java.lang包是java语言的核心,它提供了java中的基础类。包括基本Object类、Class类、String类、基本类型的包装类、基本的数学类等等最基本的类。 java.lang包提供利用java编程语言进行程序设计的基础类,它在程序生成时就帮你自动多加了一段程序导入了。
java中的数据类型int,double等不是对象,无法通过向上转型获取到Object提供的方法,而像String却可以,只因为String是一个对象而不是一个类型。基本数据类型由于这样的特性,导致无法参与转型,泛型,反射等过程。为了弥补这个缺陷,java提供了包装类。
有8大基本数据类型,其对应的包装类分别为:
类型 | 字节型 | 字符型 | 布尔型 | 短整型 | 整型 | 长整型 | 单精度实型 | 双精度实型 |
---|---|---|---|---|---|---|---|---|
基本数据类型名 | byte | char | boolean | short | int | long | float | double |
包装类名 | Byte | Character | Boolean | Short | Integer | Long | Float | Double |
Error(错误):通常是灾难性的致命错误,不是程序(程序猿)可以控制的,如内存耗尽、JVM系统错误、堆栈溢出等。应用程序不应该去处理此类错误,且程序员不应该实现任何Error类的子类。
Exception(异常):用户可能捕获的异常情况,可以使用针对性的代码进行处理,如:空指针异常、网络连接中断、数组下标越界等。
RuntimeException类及其子类称为非检查型异常,Java编译器会自动按照异常产生的原因引发相应类型的异常,程序中可以选择捕获处理也可以不处理,虽然Java编译器不会检查运行时异常,但是也可以去进行捕获和抛出处理。RuntimeException类和子类以及Error类都是非受检异常。
Object类是Javajava.lang包下的核心类,Object类是所有类的父类,何一个类时候如果没有明确的继承一个父类的话,那么它就是Object的子类;
Object 类属于java.lang包,此包下的所有类在使用时无需手动导入,系统会在程序编译期间自动导入
Math类定义了基本数学运算的属性和方法,所有方法都为static,可以通过math类在主函数直接调用。
所有的包装类(Integer、Long、Byte、Double、Float、Short)都是抽象类 Number 的子类;
public class Demo1 {
public static void main(String[] args) {
// 实现小数四舍五入
Double aDouble = new Double(1.73);
System.out.println(Math.round(aDouble));
}
}
System类代表系统,系统级的很多属性和控制方法都放置在该类的内部。该类位于java.lang包。
由于该类的构造方法是private的,所以无法创建该类的对象,也就是无法实例化该类。其内部的成员方法和成员变量都是static(静态)的,所以也可以很方便的调用他。
public class Demo1 {
private static final String TAG ="Demo1" ;
public static void main(String[] args) {
// 打印当前时间毫米值
System.out.println(System.currentTimeMillis());
// 复制数组
int[] i = {
1, 2, 3};
int[] j = new int[5];
System.arraycopy(i, 0, j, 2, 3);
}
}
字符串效果相当于数组(char[]),char是一个可以用来存储字符数据的变量类型,而string就是一个存储一串字符数据的变量类型,他们的共同点就是他们都是变量类型,都是用来存储字符的
字符串String是引用数据类型,char是基本数据类型
String str ="hello word";
char c1 = str.charAt(0);//c1的值为'h'
char c2 = str.chatAt(6);//c1的值为'w'
String str1 = "我每天学习";
String str2 = str1.substring(1);//str1="每天学习"
String str3 = str1.substring(0,3)//str2="我每天"
String string = new String("hello");
String str = string.replaceAll("h", "y");//str =yello
String s1 = "I am";
String s2 = " a student";
String s3 = s1 + s2;
String s4 = s1.concat(s2);
int s5 = s1.concat(s2)
System.out.println(s3);
System.out.println(s4);
System.out.println("s3=s4:"+(s3==s4));//字1符串连接逻辑异常
String str="1234@abc";
String[] a = str.split("@");
System.out.println("处理结果: "+a[0]+","+a[1]); //输出的是: 处理结果: 1234,abc
String类是不可变类,任何对String的改变都会引发新的String对象的生成;
StringBuffer是可变类,任何对它所指代的字符串的改变都不会产生新的对象,线程安全的。
StringBuilder是可变类,线性不安全的,不支持并发操作,不适合多线程中使用,但其在单线程中的性能比StringBuffer高。
StringBuffer strBuf = new StringBuffer("abc");
String str = strBuf.append("def");//str = "abcdef"
StringBuilder bu1 = new StringBuilder();
System.out.println("bu1"+bu1);// bu1
StringBuilder bu2 = new StringBuilder("abc");
System.out.println("bu2:"+bu2);// bu2:abc
List集合,有两种实现类:ArrayList、LinkedList。
ArrayList和数组类似,顺序排列,访问速度快,插入和删除速度块较慢LinkedList,采用链表数据结构,访问速度慢,插入和删除速度块
class Example8_5{
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add("a");
arrayList.add("b");
arrayList.add("c");
System.out.println("arrayList的元素为:"+arrayList);
arrayList.set(0,"c");//将索引为0的位置对象a修改为对象c
System.out.println("arrayList的元素为"+arrayList);
arrayList.add(1,"e");//将对象e添加到索引为1的位置
System.out.print("arrayList的元素为:");
for (int i=0;i<arrayList.size();i++){
System.out.print(arrayList.get(i));//for循环迭代arrayList集合元素
}
System.out.println("");
System.out.println("arrayList指定元素c位置的索引为"+arrayList.indexOf("c"));//返回列表中指定元素c位置的索引
System.out.println("arrayList指定元素c最后位置的索引为"+arrayList.lastIndexOf("c"));//返回列表中指定元素c最后位置的索引
System.out.println("arrayList的指定区域为"+arrayList.subList(1,2));//返回列表中指返回一个指定区域的List集合对象[1,2)
LinkedList linkedList = new LinkedList();
linkedList.add("a");
linkedList.add("b");
linkedList.add("c");
linkedList.add("d");
//获得并输入列表开头的对象
System.out.println("列表开头元素为:"+linkedList.getFirst()+"列表结尾元素为:"+linkedList.getLast());
linkedList.addFirst("rr");//向列表开头添加一个对象
System.out.println("列表中所有元素:"+linkedList);
linkedList.removeLast();//移除列表结尾元素
System.out.println("列表结尾元素为:"+linkedList.getLast());//获取并输出列表结尾的对象
}
}
TreeSet集合中元素唯一且已经排好序,采用额外的红黑树算法进行排序,如果需要一个保持顺序的集合时,应该选择TreeSet;
HashSet集合中元素唯一且已经排好序,它按照Hash算法进行排序,如果经常对元素进行添加、查询操作,应该选择HashSet;
LinkedHashSet是HashSet的一个子类,具有HashSet的特性,也是根据元素的hashCode值来确定元素的存储位置,它使用链表维护元素的次序,因此插入和删除性能比HashSet低,迭代访问集合中全部元素时性能高。
public class Example8_8 {
public static void main(String[] args) {
HashSet hashSet = new HashSet();
hashSet.add("a");
hashSet.add("null");
hashSet.add("b");
hashSet.add("c");
hashSet.add("d");
System.out.println("集合中的元素为:"+hashSet);
hashSet.remove("b");
System.out.println("集合中是否包含b元素:"+hashSet.contains("b"));
Object[] objects = hashSet.toArray();
System.out.print("数组中的元素为:");
for (Object o:objects){
System.out.print(o);
}
hashSet.clear();
System.out.println("\n"+"集合中是否不包含任何元素:"+hashSet.isEmpty());
TreeSet treeSet = new TreeSet();
TreeSet treeSet1 = new TreeSet();
treeSet.add(10);
treeSet.add(3);
treeSet.add(8);
treeSet.add(0);
treeSet1.add("b");
treeSet1.add("k");
treeSet1.add("z");
treeSet1.add("a");
//输出集合元素,看到集合已经处于排序状态
System.out.println("treeSet集合中的元素"+treeSet);
System.out.println("treeSet1集合中的元素"+treeSet1);
System.out.println("treeSet集合中的第一个元素:"+treeSet.first()+",treeSet集合中的最后一个元素:"+treeSet.last());
System.out.println("treeSet1集合中的第一个元素:"+treeSet1.first()+",treeSet1集合中的最后一个元素:"+treeSet1.last());
//返回集合中小于5的集合,不包含5;
System.out.println(treeSet.headSet(5));
//返回集合中小于c的集合
System.out.println(treeSet1.headSet("c"));
//返回大于等于8的集合
System.out.println(treeSet.tailSet(8));
//返回大于等于9,小于11的集合
System.out.println(treeSet.subSet(9,11));
}
}
输出结果:
集合中的元素为:[a, b, c, null, d]
集合中是否包含b元素:false
数组中的元素为:acnulld
集合中是否不包含任何元素:true
treeSet集合中的元素[0, 3, 8, 10]
treeSet1集合中的元素[a, b, k, z]
treeSet集合中的第一个元素:0,treeSet集合中的最后一个元素:10
treeSet1集合中的第一个元素:a,treeSet1集合中的最后一个元素:z
[0, 3]
[a, b]
[8, 10]
[10]
HashMap没有按照键值大小输出,如果需要对key-value进行插入、删除操作,优先使用HashMap;
TreeMap按照键值大小输出,,针对需要排序的Map,优先使用TreeMap。
public class Example8_13 {
public static void main(String[] args) {
Map map = new HashMap();
map.put(109, "PS");
map.put(107, "c语言");
map.put(108, "Js");
map.put(99, "数据结构");
map.put(99, "Java程序设计");//存在相同的key时,后插入的会被覆盖
System.out.println(map);
Map map1 = new HashMap<>();
map1.put(1001, "Bill");
map1.put(1001, "Bi");//存在相同的key时,后插入的会被覆盖
System.out.println(map1);
System.out.println(map.containsKey(99));
for(Object o:map.keySet()){
System.out.println(o+"-->"+map.get(o));
}
TreeMap treeMap = new TreeMap();
treeMap.put(10,"a");
treeMap.put(1,"a");
treeMap.put(9,null);
treeMap.put(5,"c");
treeMap.put(3,null);
System.out.println(treeMap);
System.out.println(treeMap.lastKey());
System.out.println(treeMap.headMap(2));
System.out.println(treeMap.tailMap(2));
TreeMap treeMap1 = new TreeMap(treeMap);
System.out.println(treeMap1);
}
}
输出结果:
{
99=Java程序设计, 107=c语言, 108=Js, 109=PS}
{
1001=Bi}
true
99-->Java程序设计
107-->c语言
108-->Js
109-->PS
{
1=a, 3=null, 5=c, 9=null, 10=a}
10
{
1=a}
{
3=null, 5=c, 9=null, 10=a}
{
1=a, 3=null, 5=c, 9=null, 10=a}
- 使用普通for循环
- 利用foreach循环迭代
- 迭代器遍历
class Example8_2 {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add("a");
arrayList.add("b");
arrayList.add("c");
System.out.println("集合的内容为:");
//使用普通for循环
for(int i = 0; i < arrayList.size(); i++){
System.out.println(list.get(i));
}
//此外,利用foreach循环迭代访问集合
for(Object obj : arrayList){
System.out.println(obj);
}
//迭代器遍历
Iterator iterator = arrayList.iterator();//iterator()方法返回一个Iterator对象
while (iterator.hasNext()){
Object o = iterator.next();//循环输出
System.out.println(o);
}
}
Collections是针对Collection而开发的一个辅助类,定义了一系列对集合进行操作的静态方法
- Sort(element):对当前集合进行升序排序,实现Comparable接口的类,只能使用一种排序方案,这种方案叫作“自然比较”方案。
- Shuffle(element):洗牌方法,将当前集合内的数据进行随机排序。
- Reverse(element):逆序排序,对当前集合的元素按照相反的顺序进行排序
ArrayList<Integer> list = new ArrayList<>();
list.add(12);
list.add(4);
list.add(3);
list.add(5);
//将集合按照默认的规则排序,按照数字从小到大的顺序排序
Collections.sort(list);
System.out.println("list = " + list);
System.out.println("===================");
//将集合中的元素反转
Collections.reverse(list);
System.out.println("list = " + list);
//addAll方法可以往集合中添加元素,也可往集合中添加一个集合
Collections.addAll(list,9,20,56);
//打乱集合中的元素
Collections.shuffle(list);
System.out.println("list = " + list);
//Arrays.asList方法可以返回一个长度内容固定的List集合
List<String> list2 = Arrays.asList("tom", "kobe", "jordan", "tracy","westbook","yaoming","ace","stephen");
//按照字符串首字符的升序排列
Collections.sort(list2);
System.out.println("list2 = " + list2);
//这里是是使用匿名内部类来完成的
Collections.sort(list2, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
//指定比较规则,按照首字母降序来排列
return o2.charAt(0)-o1.charAt(0);
}
});
System.out.println("list2 = " + list2);
//这里是使用lambda表达式来完成
Collections.sort(list2,(o1,o2)->{
return o2.charAt(o2.length()-1)-o1.charAt(o1.length()-1);});
利用SimpleDateFormat 转换日期格式
1.获取当前系统时间
Date date = new Date();
2.实现时间的加减的两种方法
package com.algorithm;
import com.chapter5.S;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Scanner;
/**
* @Author: qp
* @Time: 2021/10/19 19:57
* @Description
*/
public class UseCalendar {
public static final String Date_Format1 = "MM-dd-yyyy HH:mm:ss:SSS";
public static final String Date_Format2 = "MM/dd/yyyy HH:mm:ss.SSS";
public static final String Date_Format3 = "dd-MM-yyyy HH:mm:ss.SSS";
public static final String Date_Format4 = "dd/MM/yyyy HH:mm:ss.SSS";
/**
* @param i
* @return 返回选择的时间格式
*/
static String choiceFormat(int i) {
String str;
switch (i) {
case 1:
str = Date_Format1;
break;
case 2:
str = Date_Format2;
break;
case 3:
str = Date_Format3;
break;
case 4:
str = Date_Format4;
break;
default:
str = Date_Format1;
break;
}
return str;
}
/**
* @param str 按照字符串格式显示当前时间
*/
static void showDateFormat(String str) {
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(str);
System.out.println(simpleDateFormat.format(date));
}
/**
* @param str 显示不同的时间
*/
static void showDateDiff(String str) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(str);
System.out.println("两天前的日期:" + simpleDateFormat.format(new Date().getTime() - 2 * 24 * 60 * 60 * 1000));
System.out.println("三天后的日期:" + simpleDateFormat.format(new Date().getTime() + 3 * 24 * 60 * 60 * 1000));
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int i = scanner.nextInt();
showDateFormat(choiceFormat(i));
showDateDiff(choiceFormat(i));
}
}
finally语句块中的return会覆盖掉catch里面的throw抛出的异常
关于异常这个知识点,我的Java必备基础十五——万字长文总结异常处理基本知识点这篇文章写的很清楚。
public class Example6_5 {
public static boolean main() throws ArithmeticException {
int a = 6;
int b = 0;
try {
if (b == 0) {
throw new ArithmeticException();//通过throw抛出异常
}
System.out.println(a / b);
}catch (ArithmeticException e){
System.out.println("除数不能为0");
throw e;//通过throw抛出异常
}finally {
return false;
}
}
public static void main(String[] args) {
try {
System.out.println(main());
}catch (Exception e){
System.out.println("捕获");
}
}
}
public class Example7_1 {
public static void main(String[] args) throws FileNotFoundException {
File file = new File("word.txt");//创建文件对象
try {
FileOutputStream fileOutputStream = new FileOutputStream(file);//通过指定文件构造文件输出流
byte[] b = "hello word".getBytes();
fileOutputStream.write(b);
} catch (IOException e) {
//catch处理write方法抛出的异常
e.printStackTrace();//输出异常消息
}
try {
FileInputStream fileInputStream = new FileInputStream(file);
byte[] b = new byte[1024];
int len = fileInputStream.read(b);//从文件中读取消息到b中并且返回读取的实际的字节数目给到len
for (int i = 0; i < len; i++) {
System.out.print((char)b[i]);//要将字节中读取到的数据转化为字符才能输出字符,否则会输出字节内容
}
//System.out.println(new String(b,0,len));//或者将字节数组b直接转化为字符串,与for循环是一样的效果
fileInputStream.close();//关闭流
} catch (IOException e) {
//catch处理write方法抛出的异常
e.printStackTrace();//输出异常消息
}
}
}