类与对象 类的创建流程 1 2 3 4 5 6 7 8 9 10 public class Puppy { public Puppy (String name) { System.out.println("小狗的名字是 : " + name ); } public static void main (String[] args) { Puppy myPuppy = new Puppy ( "tommy" ); } }
** 类的定义中只有一个参数name 代码执行从main函数开始 新建一个Puppy类myPuppy并在新建是传入参数tommy,即为name参数的内容 执行时创建传参tommy,并且在创建时执行定义中的System.out.println函数输出内容 **
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 public class Puppy { int puppyAge; public Puppy (String name) { System.out.println("小狗的名字是 : " + name ); } public void setAge ( int age ) { puppyAge = age; } public int getAge ( ) { System.out.println("小狗的年龄为 : " + puppyAge ); return puppyAge; } public static void main (String[] args) { Puppy myPuppy = new Puppy ( "tommy" ); myPuppy.setAge( 2 ); myPuppy.getAge( ); System.out.println("变量值 : " + myPuppy.puppyAge ); } } 输出结果 小狗的名字是 : tommy 小狗的年龄为 : 2 变量值 : 2 执行流程 new puppy 类 myPuppy 传参tommy到name输出小狗名字 myPuppy.setAge传参age myPuppy.getAge访问变量puppyAge 这里访问变量的方式有两种,一种是通过set和get函数,一种是类名.函数名
源文件相关规则
源文件的名称应该和 public 类的类名保持一致。
一个源文件中只能有一个 public 类
载入 java_installation/java/io 路径下的所有类
Java基本的数据类型 boolean :Java中的布尔类型数据,只有两个取值 true和false 默认为==false==
也可通过包装类(库)中.SIZE .MAX_VALUE .MIN_VALUE 函数直接通过代码给出取值范围
1 2 3 4 5 6 public class TypeTest { public static void main (String[] args) { System.out.println("byte型的二进制位数" +Byte.SIZE); System.out.println("取值范围" +Byte.MIN_VALUE+"到" +Byte.MAX_VALUE); } }
Java的值传递 Java函数中的参数传递是按值传递的,即在函数传值形成新的变量副本,不会影响到原来变量的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class RunoobTest { public static void main (String[] args) { int a = 10 , b = 20 ; swap(a, b); System.out.println("a = " + a + ", b = " + b); } public static void swap (int x, int y) { int temp = x; x = y; y = temp; } }
如果需要对原来变量的值进行修改,有如下几种方法
swap函数方法直接写到main函数中
变量a与b采用数组形式储存,这样传参时实际上就是传了引用(类似c++中数组指针)
1 2 3 4 5 6 7 8 9 10 11 12 13 public class RunoobTest { public static void main (String[] args) { int [] arr = {10 , 20 }; swap(arr); System.out.println("a = " + arr[0 ] + ", b = " + arr[1 ]); } public static void swap (int [] arr) { int temp = arr[0 ]; arr[0 ] = arr[1 ]; arr[1 ] = temp; } }
类变量(静态变量) public static int count1 = 0;
1 2 3 4 5 public class MyClass { public static int count1 = 0 ; public static int count2 = count1 + 1 ; }
静态变量是可变的,类名.变量名或者实例名.变量名都可以访问,多个相同类型类里面只能有一个同名静态变量,与之对比的是常量 静态变量的一个重要用途是用于计数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class Counter { private static int count = 0 ; public Counter () { count++; } public static int getCount () { return count; } public static void main (String[] args) { Counter c1 = new Counter (); Counter c2 = new Counter (); Counter c3 = new Counter (); System.out.println("目前为止创建的对象数: " + Counter.getCount()); } }
每创建一个count值就+1
常量 常量的值是不可变的,常用于类的固定属性,也可于静态变量配合public static final int BOXWIDTH = 6;
final 继承 final 方法(函数)可以被继承,但不能修改内容 fianl 类不可以被继承
1 public final class Test {
do while 循环
先执行一次代码在进行判断,如果符合条件就开始循环,直到最后一次判定不通过
增强 for 循环 增强for循环实际上就是for-each循环 定义:
1 2 3 for (元素类型 元素变量 : 集合) { }
例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class Testfor { public static void main (String[] args) { int [] numbers = {10 , 20 , 30 , 40 , 50 }; for (int x : numbers ){ System.out.print( x ); System.out.print("," ); } System.out.print("\n" ); String [] names ={"James" , "Larry" , "Tom" , "Lacy" }; for ( String name : names ) { System.out.print( name ); System.out.print("," ); } } }
这里两个for-each循环分别实现了按顺序遍历数组中的元素 第一个循环实现了在int型的bumbers数组对象中顺序取出了每一个int类型元素 第二个循环取出了String类型的元素
continue continue; 用于跳转到下一条循环
if…else if…else 1 2 3 4 5 6 7 8 9 if (布尔表达式 1 ){ }else if (布尔表达式 2 ){ }else if (布尔表达式 3 ){ }else { }
无论是if…else if…else还是if…else 都不需要考虑缩进
switch case 条件语句 1 2 3 4 5 6 7 8 9 10 11 switch (expression){ case value : break ; case value : break ; default : }
expression是需要匹配的==表达式==或值case value匹配值,匹配后再执行对应语句 需要注意的是,当前case已经匹配,而且没有break跳出判断,那么后面所有case的语句都会被执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class Test { public static void main (String args[]) { int i = 1 ; switch (i){ case 0 : System.out.println("0" ); case 1 : System.out.println("1" ); case 2 : System.out.println("2" ); default : System.out.println("default" ); } } } output: 1 2 default
数据类型的包装类 Java Number & Math 类 1 2 3 4 5 6 7 8 public class Test { public static void main (String[] args) { Integer x = 5 ; x = x + 10 ; System.out.println(x); } }
如以上代码中的Integer x = 5,这样使用包装类直接定义基本数据类型数据时,可以用于对应函数只==允许传参对象==的情况,因为直接使用包装类进行定义,实际上就是创建了对应的数据对象
1 2 3 4 5 6 7 8 9 10 11 |包装类|基本数据类型| |---|---| |Boolean|boolean| |Byte|byte| |Short|short| |Integer|int| |Long|long| |Character|char| |Float|float| |Double|double| 这里是包装类与对应数据类型的对照表
String 类 String创建字符串的两种方式:
String s1 = “谁是带篮子” 这样创建的字符串存储在公共池中,创建时会先对字符进行搜索,如果已经存在就直接返回引用。
String s2 = new String(“谁是带篮子”) 使用new创建的字符串存放在堆中,即使相同字符也会创建新的对象 注意 String创建的对象一旦创建是不可以进行更改的,在某些情况下,需要对已经创建的字符串进行修改,这就出现了==StringBuffer 和 StringBuilder 类==
StringBuffer 和 StringBuilder 类 这两种类创建的字符串对象可以进行多次修改,而且不会产生新的对象 这两种类都是对对象本身进行操作,区别在于:
StringBuffer是线程安全的,即多个线程可以同时访问和修改StringBuffer对象,不会引起并发问题
StringBuilder没有线程安全性,但由于不需要进行线程同步,使用一般单线程的程序使用StringBuilder创建对象性能较高,速度较快
StringBuilder 类的对象创建及相关函数(使用方法) 1 2 3 4 5 6 7 8 9 10 11 12 13 public class RunoobTest { public static void main (String args[]) { StringBuilder sb = new StringBuilder (10 ); sb.append("Runoob.." ); System.out.println(sb); sb.append("!" ); System.out.println(sb); sb.insert(8 , "Java" ); System.out.println(sb); sb.delete(5 ,8 ); System.out.println(sb); } }
实际上类似于c++中对于字符串数组的修改 在程序对于线程安全有要求时必须使用==StringBuffer== 需要注意的是==StringBuilder sb = “aaa”;==这样的用法是错误的 StringBuilder是一个类,不能直接像String一样快捷创建字符串,必须要先创建一个空的可变字符串对象,再使用.append(“this is string”)函数填充内容tringBuilder sb = new StringBuilder();
数组 定义 1 2 3 4 5 dataType[] arrayRefVar; arrayRefVar = new dataType [arraySize]; dataType[] arrayRefVar = {value0, value1, ..., valuek};
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 TestArray { public static void main (String[] args) { int size = 10 ; double [] myList = new double [size]; myList[0 ] = 5.6 ; myList[1 ] = 4.5 ; myList[2 ] = 3.3 ; myList[3 ] = 13.2 ; myList[4 ] = 4.0 ; myList[5 ] = 34.33 ; myList[6 ] = 34.0 ; myList[7 ] = 45.45 ; myList[8 ] = 99.993 ; myList[9 ] = 11123 ; double total = 0 ; for (int i = 0 ; i < size; i++) { total += myList[i]; } System.out.println("总和为: " + total); } }
这里同时声明并创建了double类型的数组myList,大小为10个字符 需要注意的是Java的数组是严格的,一旦创建之后长度就不可以改变,但是Java中动态数据有着其他的结构可以使用,例如ArrayList
1 2 3 4 5 6 7 8 9 10 11 12 import java.util.ArrayList;ArrayList<String> fruits = new ArrayList <String>(); fruits.add("Apple" ); fruits.add("Banana" ); fruits.add("Orange" ); String fruit = fruits.get(0 );System.out.println(fruit);
For-Each循环 遍历数组
1 2 3 4 5 6 7 8 9 10 public class TestArray { public static void main (String[] args) { double [] myList = {1.9 , 2.9 , 3.4 , 3.5 }; for (double element: myList) { System.out.println(element); } } }
这种特殊的循环会自己更新下标来寻找数组中的所有元素
数组传参 1 2 3 4 5 public static void printArray (int [] array) { for (int i = 0 ; i < array.length; i++) { System.out.print(array[i] + " " ); } }
1 printArray(new int []{3 , 1 , 2 , 6 , 4 , 2 });
这里说明了Java数组的传参方式实际上跟c++没有任何区别
Arrays 类 java.util.Arrays类中有很多成熟的函数可供使用
1 2 3 4 5 6 7 8 public static int binarySearch (Object[] a, Object key) public static boolean equals (long [] a, long [] a2) public static void fill (int [] a, int val) public static void sort (Object[] a)
日期时间 获取当时时间🌰
1 2 3 4 5 6 7 8 9 10 11 import java.util.Date; public class DateDemo { public static void main (String[] args) { Date date = new Date (); System.out.println(date.toString()); } }
long getTime( )这个函数用于返回自1970.1.1 00.00以来的毫秒值,常用于计算,而上面用到的String toString( )函数用于返回一个指定格式的时间
指定格式输出时间 🌰
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import java.util.*;import java.text.*; public class DateDemo { public static void main (String[] args) { Date dNow = new Date ( ); SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss" ); System.out.println("当前时间为: " + ft.format(dNow)); } }
创建了一个ft对象,并使用SimpleDateFormat函数对.format()函数要使用的格式进行了规定,ft.format(dNow)函数用于输出对应格式的时间对象
printf中的时间格式化方法 这种格式化输出的方法能够直接在输出的过程中选择需要输出的内容 先给出一个🌰
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import java.util.Date; public class DateDemo { public static void main (String[] args) { Date date = new Date (); System.out.printf("全部日期和时间信息:%tc%n" ,date); System.out.printf("年-月-日格式:%tF%n" ,date); System.out.printf("月/日/年格式:%tD%n" ,date); System.out.printf("HH:MM:SS PM格式(12时制):%tr%n" ,date); System.out.printf("HH:MM:SS格式(24时制):%tT%n" ,date); System.out.printf("HH:MM格式(24时制):%tR" ,date); } }
输出结果:
代码中给出了几个常用的printf输出时间的简单格式,大多数情况已经足够
字符串转date对象 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 import java.text.SimpleDateFormat;import java.util.Date;import java.util.Scanner;public class UserInputStringToTime { public static void main (String[] args) { String dateFormat = "yyyy-MM-dd HH:mm:ss" ; SimpleDateFormat sdf = new SimpleDateFormat (dateFormat); Scanner scanner = new Scanner (System.in); System.out.print("请输入日期时间字符串(格式:" + dateFormat + "):" ); String userInput = scanner.nextLine(); try { Date date = sdf.parse(userInput); System.out.println("解析结果:" + date); } catch (Exception e) { System.out.println("日期时间格式不匹配或解析失败。" ); } finally { scanner.close(); } } }
数值化计算时间间隔 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.*; public class DiffDemo { public static void main (String[] args) { try { long start = System.currentTimeMillis( ); System.out.println(new Date ( ) + "\n" ); Thread.sleep(5 *60 *10 ); System.out.println(new Date ( ) + "\n" ); long end = System.currentTimeMillis( ); long diff = end - start; System.out.println("Difference is : " + diff); } catch (Exception e) { System.out.println("Got an exception!" ); } } }
这里使用System.currentTimeMillis( )来获取当前时间的毫秒值 同时使用了try catch方法来实现一个执行并异常处理的逻辑,如果休眠未成功,就会自动进入catch异常处理块中,并抛出异常
java中的休眠 Thread.sleep()函数用于阻塞当前进程,参数单位是毫秒
1 2 3 4 5 6 7 8 9 10 11 12 13 import java.util.*; public class SleepDemo { public static void main (String[] args) { try { System.out.println(new Date ( ) + "\n" ); Thread.sleep(1000 *3 ); System.out.println(new Date ( ) + "\n" ); } catch (Exception e) { System.out.println("休眠失败" ); } } }
实践应用中常用于脚本频率检测机制的反制,可见用途:抢票,爆破,爬虫
Calendar类 之前我们已经实现了日期的读取,写入,格式化,但是对于日期的指定数据的获取,数值计算,还没有特别好的方法实现,使用在这里引入了Calendar类来处理这些问题,Calendar和Date类类似,但是有着更加强大的功能
日期对象创建
1 Calendar c = Calendar.getInstance();
1 2 3 Calendar c1 = Calendar.getInstance();c1.set(2023 , 6 - 1 , 12 );
可以发现当创建对象时,使用的Calendar.getInstance()对象默认创建的都是当前日期,需要指定日期时,在创建对象后再使用.set函数指定 需要注意的是,这里并没有使用c1.clear();来清除所有数据,所以未设定的数据还是获取到的当前时间
set使用
1 2 public final void set (int year,int month,int date) c1.set(2009 , 6 , 12 );
1 2 3 4 5 public void set (int field,int value) c1.set(Calendar.DATE,10 ); c1.set(Calendar.MONTH,11 ); c1.set(Calendar.YEAR,2008 );
附上对应表
1 2 3 4 c1.add(Calendar.DATE, 10 ); c1.add(Calendar.DATE, -10 );
get获取部分日期数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 Calendar c1 = Calendar.getInstance();int year = c1.get(Calendar.YEAR);int month = c1.get(Calendar.MONTH) + 1 ;int date = c1.get(Calendar.DATE);int hour = c1.get(Calendar.HOUR_OF_DAY);int minute = c1.get(Calendar.MINUTE);int second = c1.get(Calendar.SECOND);int day = c1.get(Calendar.DAY_OF_WEEK);
这里发现Calendar的月份时从0开始的
GregorianCalendar类 GregorianCalendar实现了公历的日期格式 这里只给出一个简单的利用案例
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 import java.util.*; public class GregorianCalendarDemo { public static void main (String[] args) { String months[] = { "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "11" , "12" }; int year; GregorianCalendar gcalendar = new GregorianCalendar (); System.out.print("日期: " ); System.out.print(months[gcalendar.get(Calendar.MONTH)]); System.out.print(" " + gcalendar.get(Calendar.DATE) + " " ); System.out.println(year = gcalendar.get(Calendar.YEAR)); System.out.print("时间: " ); System.out.print(gcalendar.get(Calendar.HOUR) + ":" ); System.out.print(gcalendar.get(Calendar.MINUTE) + ":" ); System.out.println(gcalendar.get(Calendar.SECOND)); if (gcalendar.isLeapYear(year)) { System.out.println("当前年份是闰年" ); } else { System.out.println("当前年份不是闰年" ); } } }
这里只需要学会GregorianCalendar gcalendar = new GregorianCalendar(); 这样使用默认时间创建即可,这样创建的日期还有着闰年判断,可以少写一段闰年判断
Java正则表达式 正则表达式常用于文本的格式筛选和处理
一个字符串就是一个简单的正则表达式,例如this is text就能匹配==”this is text”==字符
this\s+is\s+text这里的\s+用于匹配一个或者多个空格,所以这里匹配的字符同样包含上述字符
^\d+(\.\d+)?
1 2 3 4 5 6 7 8 9 ^ 定义了以什么开始 \d+ 匹配一个或多个数字 ? 设置括号内的选项是可选的 \. 匹配 "." 可以匹配的实例:"5", "1.5" 和 "2.21"。
Java的正则来自java.util.regex包 包中有Pattern 类,Matcher 类,PatternSyntaxException类 实际上,用法是Pattern类创建对象,Marcher进行匹配,PatternSyntaxException进行语法异常处理 给出一个简单的例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import java.util.regex.*; class RegexExample1 { public static void main (String[] args) { String content = "I am noob " + "from runoob.com." ; String pattern = ".*runoob.*" ; boolean isMatch = Pattern.matches(pattern, content); System.out.println("字符串中是否包含了 'runoob' 子字符串? " + isMatch); } }
这里较为具体的用法和原理暂且按下不表,在实际应用时直接生成时再针对理解
Java 方法 System.out.println()这里就是调用系统类System中的标准输出对象out中的方法println() 方法的定义就是包含在类或对象中,解决某一类问题的步骤的有序组合,然后能被其他地方引用 其实就是其他程序语言中的函数 结构如下
1 2 3 4 5 6 修饰符 返回值类型 方法名(参数类型 参数名){ ... 方法体 ... return 返回值; }
常规的用法跟c++没区别,需要注意的是调用方法值传参时会创建参数副本,修改并不会影响到原来参数
重载 1 2 3 4 5 6 public static double max (double num1, double num2) { if (num1 > num2) return num1; else return num2; }
这里给出了一个例子,相同方法名,但是传递参数的数据类型不同,就会执行不同的代码块 这种方法重写就叫重载
可变参数 可变参数的类型是数组 声明参数
1 typeName... parameterName
例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class VariableArguments { public static void main (String[] args) { printValues("Hello" , "World" ); printValues("Java" , "is" , "awesome" ); } public static void printValues (String... values) { for (String value : values) { System.out.println(value); } } } Hello World Java is awesome
这里通过String... values声明了方法传递的参数时可变参数values,参数的内容在调用方法时传参指定
Java 流(Stream)、文件(File)和IO 输入读取 这里读取输入有两种常见类
BufferedReader:BufferedReader 类主要用于以文本方式读取字符流,它提供了高效的缓冲机制,可以一次读取一行或指定大小的字符数据。使用 BufferedReader 可以逐行读取文本文件的内容。
Scanner:Scanner 类具有更多的功能,可以用于解析原始类型和字符串,并从输入中提取特定类型的值。它可以对不同类型的输入进行解析和筛选,并提供了方便的方法来获取用户的输入。 在实际的使用中,BufferedReader常用于文本文档或者大量输入的读取,Scanner则用于少量用户输入内容的读取 下面给出两个类获取用户输入的示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;public class BufferedReaderExample { public static void main (String[] args) { BufferedReader reader = new BufferedReader (new InputStreamReader (System.in)); try { System.out.print("请输入您的姓名: " ); String name = reader.readLine(); System.out.println("您好, " + name + "!" ); reader.close(); } catch (IOException e) { e.printStackTrace(); } } }
1 2 3 4 5 6 7 8 9 10 11 12 import java.util.Scanner;public class ScannerExample { public static void main (String[] args) { Scanner scanner = new Scanner (System.in); System.out.print("请输入您的年龄: " ); int age = scanner.nextInt(); System.out.println("您的年龄是: " + age); scanner.close(); } }
会发现实际上BufferReader类的使用较Scanner而言十分繁琐,因此在一般项目的构建中只使用Scanner类
文件读写 创建输入流对象
InputStream f = new FileInputStream("C:/java/hello");
File f = new File("C:/java/hello");InputStream in = new FileInputStream(f);
FileOutputStream 写入文件 创建输出流对象
1 2 3 4 OutputStream f = new FileOutputStream ("C:/java/hello" )File f = new File ("C:/java/hello" );OutputStream fOut = new FileOutputStream (f);
需要注意的是这两个类在写入文件时是二进制形式的,对于文本文件,我们更常用的类是BufferedReader和BufferedWriter
BufferedReader 读取文本 1 2 3 4 5 6 7 BufferedReader reader = new BufferedReader (new FileReader ("file.txt" ));String line; while ((line = reader.readLine()) != null ) { } reader.close();
BufferedWriter 写入文本 1 2 3 4 5 BufferedWriter writer = new BufferedWriter (new FileWriter ("file.txt" ));String data = "Hello, World!" ;writer.write(data); writer.flush(); writer.close();
需要注意的是,BufferedReader和BufferedWriter都实现了AutoCloseable接口,所以可以通过try-with-resources语句(try-catch)来创建对象,这样他会自动关闭输入输出流
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.io.*;public class Example { public static void main (String[] args) { try (BufferedReader reader = new BufferedReader (new FileReader ("input.txt" )); BufferedWriter writer = new BufferedWriter (new FileWriter ("output.txt" ))) { String line; while ((line = reader.readLine()) != null ) { writer.write(line); writer.newLine(); } } catch (IOException e) { e.printStackTrace(); } } }
目录 创建目录 1 2 3 4 5 6 7 8 9 10 import java.io.File; public class CreateDir { public static void main (String[] args) { String dirname = "/tmp/user/java/bin" ; File d = new File (dirname); d.mkdirs(); } }
读取目录 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.io.File; public class DirList { public static void main (String args[]) { String dirname = "/tmp" ; File f1 = new File (dirname); if (f1.isDirectory()) { System.out.println("目录 " + dirname); String s[] = f1.list(); for (int i = 0 ; i < s.length; i++) { File f = new File (dirname + "/" + s[i]); if (f.isDirectory()) { System.out.println(s[i] + " 是一个目录" ); } else { System.out.println(s[i] + " 是一个文件" ); } } } else { System.out.println(dirname + " 不是一个目录" ); } } }
直接读取路径,isDirectory()判断是否为目录
删除目录 java.io.File.delete() 这个方法只能删除空目录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import java.io.File; public class DeleteFileDemo { public static void main (String[] args) { File folder = new File ("/tmp/java/" ); deleteFolder(folder); } public static void deleteFolder (File folder) { File[] files = folder.listFiles(); if (files != null ) { for (File f : files) { if (f.isDirectory()) { deleteFolder(f); } else { f.delete(); } } } folder.delete(); } }
递归遍历每个不为空的文件夹,删除其中文件,检查为空则删除文件夹 这样实现了删除指定目录下的所有文件
Java Scanner 类 调用Scannner类获取用户输入 创建对象
1 Scanner s = new Scanner (System.in);
简单例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.Scanner; public class ScannerDemo { public static void main (String[] args) { Scanner scan = new Scanner (System.in); System.out.println("nextLine方式接收:" ); if (scan.hasNextLine()) { String str2 = scan.nextLine(); System.out.println("输入的数据为:" + str2); } scan.close(); } }
nextLine方法只会识别回车为结束输入
next方法不会接收空格后输入,仍然是回车结束输入
这里给出一个输入作为变量的简单例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import java.util.Scanner;public class Main { public static void main (String[] args) { Scanner scanner = new Scanner (System.in); System.out.print("请输入一组字符串,以空格分隔:" ); String input = scanner.nextLine(); String[] strings = input.split(" " ); System.out.println("您输入的字符串数组为:" ); for (String str : strings) { System.out.println(str); } scanner.close(); } }
hasNextXxx()方法可以判断输入类型,返回值为bool类型,建议在每次输入时首先检验,避免恶意代码强制闭合注入😈
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 import java.util.Scanner; public class ScannerDemo { public static void main (String[] args) { Scanner scan = new Scanner (System.in); int i = 0 ; float f = 0.0f ; System.out.print("输入整数:" ); if (scan.hasNextInt()) { i = scan.nextInt(); System.out.println("整数数据:" + i); } else { System.out.println("输入的不是整数!" ); } System.out.print("输入小数:" ); if (scan.hasNextFloat()) { f = scan.nextFloat(); System.out.println("小数数据:" + f); } else { System.out.println("输入的不是小数!" ); } scan.close(); } }
这里同时体现了输入为int类型的常用获取输入方法 需要注意不能忘记在末尾==scan.close();==
异常处理 捕获异常 1 2 3 4 5 6 7 8 try { }catch (ExceptionName e1) { }
try中执行代码,如果产生异常就会将异常类型传到catch块,根据对应的异常名称,执行不同的代码 给出一个实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import java.io.*;public class ExcepTest { public static void main (String args[]) { try { int a[] = new int [2 ]; System.out.println("Access element three :" + a[3 ]); }catch (ArrayIndexOutOfBoundsException e){ System.out.println("Exception thrown :" + e); } System.out.println("Out of the block" ); } }
这里访问了大小为2的数组的第四个元素,产生了数组索引越界异常,传到catch块,发现异常名称匹配,执行了输出报错信息
这里的System.out.println(“Out of the block”);是是否执行catch块都会执行的部分
多重捕获块 1 2 3 4 5 6 7 8 9 try { }catch (异常类型1 异常的变量名1 ){ }catch (异常类型2 异常的变量名2 ){ }catch (异常类型3 异常的变量名3 ){ }
发生异常后逐个catch块匹配异常类型
finally关键字 在finally段中的代码在try-catch执行完后总会被执行
1 2 3 4 5 6 7 8 9 try { }catch (异常类型1 异常的变量名1 ){ }catch (异常类型2 异常的变量名2 ){ }finally { }
🌰
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class ExcepTest { public static void main (String args[]) { int a[] = new int [2 ]; try { System.out.println("Access element three :" + a[3 ]); }catch (ArrayIndexOutOfBoundsException e){ System.out.println("Exception thrown :" + e); } finally { a[0 ] = 6 ; System.out.println("First element value: " +a[0 ]); System.out.println("The finally statement is executed" ); } } }
throws/throw关键字 1 2 3 4 5 public void checkNumber (int num) { if (num < 0 ) { throw new IllegalArgumentException ("Number must be positive" ); } }
throw关键字抛出异常,实际上用来告知调用者当前代码的执行情况,类似于输出报错语句
throws是在方法的声明中指定可能抛出的异常类型,并且传给调用的函数,可以同时指定多个异常类型 例子
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 public class Main { public static void main (String[] args) { String filePath = "example.txt" ; try { readFile(filePath); } catch (IOException e) { System.err.println("An error occurred while reading the file: " + e.getMessage()); } } public static void readFile (String filePath) throws IOException { BufferedReader reader = null ; try { reader = new BufferedReader (new FileReader (filePath)); String line = reader.readLine(); while (line != null ) { System.out.println(line); line = reader.readLine(); } } finally { if (reader != null ) { reader.close(); } } } }
这里在readFile函数声明中指定了可能抛出IOException,在调用的catch块中匹配到readFile抛出的IOException,执行对应的处理
throw/throws的区别实际上是一个是直接在方法中输出报错信息,一个是由方法抛出异常,在调用代码中再处理异常
try-with-resources 自动关闭资源 结构
1 2 3 4 5 try (resource declaration) { } catch (ExceptionType e1) { }
在try中声明资源,在catch中处理资源关闭可能引发的异常 这样实现了能自动关闭所有含AutoCloseable 接口的资源。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.io.*;public class RunoobTest { public static void main (String[] args) { String line; try (BufferedReader br = new BufferedReader (new FileReader ("test.txt" ))) { while ((line = br.readLine()) != null ) { System.out.println("Line =>" +line); } } catch (IOException e) { System.out.println("IOException in try block =>" + e.getMessage()); } } }
同时处理多个资源 在处理多个资源时,只需要资源声明之间加上;即可
1 2 3 4 5 6 7 8 9 10 11 12 class RunoobTest { public static void main (String[] args) throws IOException{ try (Scanner scanner = new Scanner (new File ("testRead.txt" )); PrintWriter writer = new PrintWriter (new File ("testWrite.txt" ))) { while (scanner.hasNext()) { writer.print(scanner.nextLine()); } } } }
这里实现了两个资源一起使用,逐行读取内容写入到testWrite.txt 这里没有写catch对于异常的处理,但并不会造成问题 换成更常用的Buffered来读取写入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class RunoobTest { public static void main (String[] args) { try (BufferedReader reader = new BufferedReader (new FileReader ("testRead.txt" )); BufferedWriter writer = new BufferedWriter (new FileWriter ("testWrite.txt" ))) { String line; while ((line = reader.readLine()) != null ) { writer.write(line); } } catch (IOException e) { System.out.println("An error occurred: " + e.getMessage()); } } }
这里如果需要指定行读取,可以通过添加计数器与指定数值进行比较来实现
异常的构建 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.io.*; public class InsufficientFundsException extends Exception { private double amount; public InsufficientFundsException (double amount) { this .amount = amount; } public double getAmount () { return amount; } }
需要注意的是需要继承Exception类 当放在一个文件夹(包)内时,直接正常抛出异常就行
继承 格式
1 2 3 4 5 class 父类 { } class 子类 extends 父类 { }
实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class Animal { private String name; private int id; public Animal (String myName, int myid) { name = myName; id = myid; } public void eat () { System.out.println(name+"正在吃" ); } public void sleep () { System.out.println(name+"正在睡" ); } public void introduction () { System.out.println("大家好!我是" + id + "号" + name + "." ); } }
1 2 3 4 5 6 public class Penguin extends Animal { public Penguin (String myName, int myid) { super (myName, myid); } }
1 2 3 4 5 6 public class Mouse extends Animal { public Mouse (String myName, int myid) { super (myName, myid); } }
这里的企鹅类和老鼠类都继承了父类animals的属性和方法,分别写了自己的构造函数,但是在构造函数中使用super函数调用了父类的构造函数初始化myName属性和myid属性 这里需要注意的是java的继承中,不支持多个父类的多继承,但是支持多次继承
继承关键字 extends关键字 extends关键字是默认使用的继承关键字,属于单一继承,一个子类只能有一个父类,一次只能继承一个类 之前的实例使用的是该关键字
implements关键字 这里使用interface构造接口,然后使用implements关键字,可以实现继承多个接口 这里给出继承和重写的一个例子
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 public interface A { public void eat () ; public void sleep () ; } public interface B { public void show () ; } public class C implements A , B { @Override public void eat () { System.out.println("C is eating" ); } @Override public void sleep () { System.out.println("C is sleeping" ); } @Override public void show () { System.out.println("C is showing" ); } }
这里C类继承了A,B两个接口,并且重写了其中的函数
super 与 this 关键字 spuer函数执行当前类的父类
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 class Animal { void eat () { System.out.println("animal : eat" ); } } class Dog extends Animal { void eat () { System.out.println("dog : eat" ); } void eatTest () { this .eat(); super .eat(); } } public class Test { public static void main (String[] args) { Animal a = new Animal (); a.eat(); Dog d = new Dog (); d.eatTest(); } } animal : eat dog : eat animal : eat
这里Dog类中super.eat相当于Animal.eat,this.eat相当于Dog.eat
final 关键字 flinal关键字可以用于类,方法,和变量
1 2 3 final class MyClass { }
fianl类不可被继承
1 2 3 4 5 6 7 8 9 10 class Parent { final void myMethod () { } } class Child extends Parent { }
final方法不可以被子类重写或者覆盖
1 final int myConstant = 10 ;
final变量被赋值后不可以被修改
重写(Override)与重载(Overload) 重写(Override) 子类继承的父类函数外壳不变,内容重写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Animal { public void move () { System.out.println("动物可以移动" ); } } class Dog extends Animal { public void move () { System.out.println("狗可以跑和走" ); } } public class TestDog { public static void main (String args[]) { Animal a = new Animal (); Animal b = new Dog (); a.move(); b.move(); } }
这里Animal b = new Dog(); // Dog 对象向上转型,使用的所有函数都是Dog类中函数,但不包括Dog类独有的函数
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 class Animal { public void move () { System.out.println("动物可以移动" ); } } class Dog extends Animal { public void move () { System.out.println("狗可以跑和走" ); } public void bark () { System.out.println("狗可以吠叫" ); } } public class TestDog { public static void main (String args[]) { Animal a = new Animal (); Animal b = new Dog (); a.move(); b.move(); b.bark(); } }
这里运行到b.bark()会抛出编译错误,因为这里的b对象,是Dog对象向上转型来的,没有Dog中独有的bark方法
swing框架使用 一元二次求根案例
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 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class QuadraticRootsCalculator extends JFrame implements ActionListener { private JTextField coefficientAField; private JTextField coefficientBField; private JTextField coefficientCField; private JTextField root1Field; private JTextField root2Field; public QuadraticRootsCalculator () { setTitle("一元二次方程求根" ); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(400 , 300 ); setLocationRelativeTo(null ); JPanel panel = new JPanel (); panel.setLayout(null ); JLabel coefficientALabel = new JLabel ("系数 a:" ); coefficientALabel.setBounds(10 , 20 , 80 , 25 ); panel.add(coefficientALabel); coefficientAField = new JTextField (10 ); coefficientAField.setBounds(100 , 20 , 165 , 25 ); panel.add(coefficientAField); JLabel coefficientBLabel = new JLabel ("系数 b:" ); coefficientBLabel.setBounds(10 , 50 , 80 , 25 ); panel.add(coefficientBLabel); coefficientBField = new JTextField (10 ); coefficientBField.setBounds(100 , 50 , 165 , 25 ); panel.add(coefficientBField); JLabel coefficientCLabel = new JLabel ("系数 c:" ); coefficientCLabel.setBounds(10 , 80 , 80 , 25 ); panel.add(coefficientCLabel); coefficientCField = new JTextField (10 ); coefficientCField.setBounds(100 , 80 , 165 , 25 ); panel.add(coefficientCField); JLabel root1Label = new JLabel ("根 1:" ); root1Label.setBounds(10 , 110 , 80 , 25 ); panel.add(root1Label); root1Field = new JTextField (10 ); root1Field.setBounds(100 , 110 , 165 , 25 ); root1Field.setEditable(false ); panel.add(root1Field); JLabel root2Label = new JLabel ("根 2:" ); root2Label.setBounds(10 , 140 , 80 , 25 ); panel.add(root2Label); root2Field = new JTextField (10 ); root2Field.setBounds(100 , 140 , 165 , 25 ); root2Field.setEditable(false ); panel.add(root2Field); JButton calculateButton = new JButton ("求根" ); calculateButton.setBounds(10 , 180 , 80 , 25 ); calculateButton.addActionListener(this ); panel.add(calculateButton); JButton exitButton = new JButton ("退出" ); exitButton.setBounds(100 , 180 , 80 , 25 ); exitButton.addActionListener(this ); panel.add(exitButton); add(panel); } public static void main (String[] args) { SwingUtilities.invokeLater(() -> { QuadraticRootsCalculator calculator = new QuadraticRootsCalculator (); calculator.setVisible(true ); }); } @Override public void actionPerformed (ActionEvent e) { if (e.getActionCommand().equals("求根" )) { double a = Double.parseDouble(coefficientAField.getText()); double b = Double.parseDouble(coefficientBField.getText()); double c = Double.parseDouble(coefficientCField.getText()); double discriminant = b * b - 4 * a * c; if (discriminant > 0 ) { double root1 = (-b + Math.sqrt(discriminant)) / (2 * a); double root2 = (-b - Math.sqrt(discriminant)) / (2 * a); root1Field.setText(String.valueOf(root1)); root2Field.setText(String.valueOf(root2)); } else if (discriminant == 0 ) { double root = -b / (2 * a); root1Field.setText(String.valueOf(root)); root2Field.setText(String.valueOf(root)); } else { root1Field.setText("无解" ); root2Field.setText("无解" ); } } else if (e.getActionCommand().equals("退出" )) { System.exit(0 ); } } }