JAVA知识结构
Java编译
关于编译型语言和解释型语言
编译型语言是直接转换为机器码执行,不同的平台CPU的指令集不同。 解释型语言是解释器直接加载源码运行,代价就是运行效率低。编译型语言如C、C++,解释型语言如Python、Ruby。
Java鉴于解释型编译型之间,是先编译成一种“字节码”,然后根据不同平台编写虚拟机,以虚拟机加载“字节码”运行。如JVM。
JAVA编译过程
Java源代码 —编译器—> Jvm可执行的Java字节码 —解释器—> 机器可执行的二进制机器码 —> 程序运行
java源代码:
class文件直接打开
class文件反编译后
Hello World
1 2 3 4 5 public class HelloWorld { public static void main (String[] args) { System.out.println("Hello World" ); } }
此时这里想讲一下public static void main(String[] args)
:
这是 Java 程序的入口地址,Java 虚拟机运行程序的时候首先找的就是 main 方法。 跟 C 语言
里面的 main() 函数
的作用是一样的。只有有 main() 方法的 Java 程序才能够被 Java 虚拟机运行 ,可理解为规定的格式。
public
public 表示这个程序的访问权限,表示的是任何场合都可以被引用;这样的效果就是Java虚拟机就可以找到main()
方法,从而来运行javac
程序。
static
static 表明方法是静态的,不依赖类的对象的,是属于类的,在类加载的时候 main()
方法也随着加载到内存中去
void main()
**void:main()**:方法是不需要返回值的。
main
约定熟成
string[] args
String[] args :从控制台接收参数。
Java对象和类
对象
对象是类的一个实例,对象有状态和行为;
类
类是一个模板;它描述了一类对象的状态和行为
此时用一张直观的图来描述对象和类的关系:此时的汽车为类(class) ;而下面的每一辆汽车为该类的对象(object) ;对象包含了自身的状态和行为(类似于下图的颜色、品牌、名称等)
创建一个简单的类
类可以看作创建Java
对象的模板;此时可以依据下图创建一个简单的类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class Dog { String breed; int size; String colour; int age; void eat () { } void run () { } void sleep () { } void name () { } }
一个类可以拥有多个方法,在上面的例子中:eat()、run()、sleep() 和 name()
都是 Dog
类的方法。
构造方法
在每个类中都有其构造方法;在创建一个对象时至少要调用一个构造方法。构造方法必须与类同名
1 2 3 4 5 6 7 8 public class Puppy { public Puppy () { } pubilc Puppy (String name) { } }
创建对象
对象是根据类创建的。在Java
中,使用new 来创建一个新的对象。创建对象需要分三步:
声明 :声明一个对象,包括对象名称和对象类型
实例化 :使用new来创建一个对象
初始化 :使用new创建对象时,会调用构造方法初始化对象
demo
1 2 3 4 5 6 7 8 9 10 public class Puppy { public Puppy (String name) { System.out.println("The dog's name is: " + name) } public static void main (String[] args) { puppy myPuppy = new Puppy ("tommy" ); } }
访问实例变量和方法
1 2 3 4 5 6 Object referenceVariable = new Constructor ();referenceVariable.variablename; referenceVariable.methodName();
访问实例变量和调用成员方法的demo
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 Puppy { int puppyAge; public Puppy (String name) { System.out.println("The dog's name is: " + name) } public void setAge (inrt age) { puppyAge = age; } public int getAge () { System.out.println("The dog's age is: " + puppyAge); return puppyAge; } public static void main (String[] args) { Puppy myPuppy = new Puppy ("tommy" ); myPuppy.setAge(2 ); myPuppy.getAge(); System.out.println("变量值" + myPuppy.puppyAge); } }
Java包和import语句
包的作用主要用来对类和接口进行分类。当开发Java程序时可能会编写很多类;此时我们就可以使用import 语句提供一个合理路径,使得编辑器可以找到某个类。
例如下面的命令将命令编辑器载入java_installation/java/io
路径下的所有类
此时我们可以通过下面的例子来理解
Employee
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.io.*;public class Employee { String name; int age; String designation; double salary; public Employee (String name) { this .name = name; } public void empAge (int empAge) { age = empAge; } public void empDesignation (String empDesig) { designation = empDesig; } public void empSalary (double empSalary) { salary = empSalary; } public void printEmployee () { System.out.println("名字:" + name ); System.out.println("年龄:" + age ); System.out.println("职位:" + designation ); System.out.println("薪水:" + salary); } }
EmployeeTest
程序都是从main
方法开始执行的。此时为了运行上面的程序,必须包含main
方法并且创建一个实例对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import java.io.*;public class EmployeeTest { public static void main (String[] args) { Employee empOne = new Employee ("RUNOOB1" ); Employee empTwo = new Employee ("RUNOOB2" ); empOne.empAge(26 ); empOne.empDesignation("高级程序员" ); empOne.empSalary(1000 ); empOne.printEmployee(); empTwo.empAge(21 ); empTwo.empDesignation("菜鸟程序员" ); empTwo.empSalary(500 ); empTwo.printEmployee(); } }
此时运行上述程序即可得到下面的结果
1 2 3 4 5 6 7 8 名字:RUNOOB1 年龄:26 职位:高级程序员 薪水:1000.0 名字:RUNOOB2 年龄:21 职位:菜鸟程序员 薪水:500.0
Java的数据类型
byte
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class PrimitiveTypeTest { public static void main (String[] args) { System.out.println("基本类型:byte 二进制位数:" + Byte.SIZE); System.out.println("包装类:java.lang.Byte" ); System.out.println("最小值:Byte.MIN_VALUE=" + Byte.MIN_VALUE); System.out.println("最大值:Byte.MAX_VALUE=" + Byte.MAX_VALUE); System.out.println(); } } # result 基本类型:byte 二进制位数:8 包装类:java.lang.Byte 最小值:Byte.MIN_VALUE=-128 最大值:Byte.MAX_VALUE=127
short
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class PrimitiveTypeTest { public static void main (String[] args) { System.out.println("基本类型:short 二进制位数:" + Short.SIZE); System.out.println("包装类:java.lang.Short" ); System.out.println("最小值:Short.MIN_VALUE=" + Short.MIN_VALUE); System.out.println("最大值:Short.MAX_VALUE=" + Short.MAX_VALUE); System.out.println(); } } # result 基本类型:short 二进制位数:16 包装类:java.lang.Short 最小值:Short.MIN_VALUE=-32768 最大值:Short.MAX_VALUE=32767
int
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class PrimitiveTypeTest { public static void main (String[] args) { System.out.println("基本类型:int 二进制位数:" + Integer.SIZE); System.out.println("包装类:java.lang.Integer" ); System.out.println("最小值:Integer.MIN_VALUE=" + Integer.MIN_VALUE); System.out.println("最大值:Integer.MAX_VALUE=" + Integer.MAX_VALUE); System.out.println(); } } # result 基本类型:int 二进制位数:32 包装类:java.lang.Integer 最小值:Integer.MIN_VALUE=-2147483648 最大值:Integer.MAX_VALUE=2147483647
long
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class PrimitiveTypeTest { public static void main (String[] args) { System.out.println("基本类型:long 二进制位数:" + Long.SIZE); System.out.println("包装类:java.lang.Long" ); System.out.println("最小值:Long.MIN_VALUE=" + Long.MIN_VALUE); System.out.println("最大值:Long.MAX_VALUE=" + Long.MAX_VALUE); System.out.println(); } } #result 基本类型:long 二进制位数:64 包装类:java.lang.Long 最小值:Long.MIN_VALUE=-9223372036854775808 最大值:Long.MAX_VALUE=9223372036854775807
float
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class PrimitiveTypeTest { public static void main (String[] args) { System.out.println("基本类型:float 二进制位数:" + Float.SIZE); System.out.println("包装类:java.lang.Float" ); System.out.println("最小值:Float.MIN_VALUE=" + Float.MIN_VALUE); System.out.println("最大值:Float.MAX_VALUE=" + Float.MAX_VALUE); System.out.println(); } } # result 基本类型:float 二进制位数:32 包装类:java.lang.Float 最小值:Float.MIN_VALUE=1.4E-45 最大值:Float.MAX_VALUE=3.4028235E38
double
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class PrimitiveTypeTest { public static void main (String[] args) { System.out.println("基本类型:double 二进制位数:" + Double.SIZE); System.out.println("包装类:java.lang.Double" ); System.out.println("最小值:Double.MIN_VALUE=" + Double.MIN_VALUE); System.out.println("最大值:Double.MAX_VALUE=" + Double.MAX_VALUE); System.out.println(); } } # result 基本类型:double 二进制位数:64 包装类:java.lang.Double 最小值:Double.MIN_VALUE=4.9E-324 最大值:Double.MAX_VALUE=1.7976931348623157E308
char
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class PrimitiveTypeTest { public static void main (String[] args) { System.out.println("基本类型:char 二进制位数:" + Character.SIZE); System.out.println("包装类:java.lang.Character" ); System.out.println("最小值:Character.MIN_VALUE=" + (int ) Character.MIN_VALUE); System.out.println("最大值:Character.MAX_VALUE=" + (int ) Character.MAX_VALUE); } } # result 基本类型:char 二进制位数:16 包装类:java.lang.Character 最小值:Character.MIN_VALUE=0 最大值:Character.MAX_VALUE=65535
变量类型
在Java
中;所有的变量在引用前都必须声明;格式如下:
1 type identifier [ = value][, identifier [= value] ...] ;
局部变量
局部变量 是在方法、构造函数或块内部声明的变量,它们在声明的方法、构造函数或块执行结束后被销毁,局部变量在声明时需要初始化,否则会导致编译错误
1 2 3 4 public void exampleMethod () { int localVar = 10 ; }
实例变量
实例变量 是在类中声明,但在方法、构造函数或块之外,它们属于类的实例,每个类的实例都有自己的副本,如果不明确初始化,实例变量会被赋予默认值(数值类型为0,boolean类型为false,对象引用类型为null)。
1 2 3 public class ExampleClass { int instanceVar; }
静态变量
类变量 是在类中用 static 关键字声明的变量,它们属于类而不是实例,所有该类的实例共享同一个类变量的值,类变量在类加载时被初始化,而且只初始化一次。
1 2 3 public class ExampleClass { static int classVar; }
参数变量
参数变量 是方法或构造函数声明中的变量,用于接收调用该方法或构造函数时传递的值,参数变量的作用域只限于方法内部。
1 2 3 4 public void exampleMethod (int parameterVar) { }
demo
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 public class RunoobTest { private int instanceVar; private static int staticVar; public void method (int paraVar) { int localVar = 20 ; instanceVar = localVar; staticVar = paramVar; System.out.println("成员变量: " + instanceVar); System.out.println("静态变量: " + staticVar); System.out.println("参数变量: " + paramVar); System.out.println("局部变量: " + localVar); } public static void main (String[] args) { RunoobTest v = new RunoobTest (); v.method(20 ); } } # result 成员变量: 10 静态变量: 20 参数变量: 20 局部变量: 10
Java修饰符
Java中,可以使用访问控制符来保护对类、变量、方法、构造方法的访问
default-默认访问修饰符
即只能被同一包中的其他类访问
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class MyClass { int x = 10 ; void display () { System.out.println("Value of x is: " + x); } } class MyOtherClass { public static void main (String[] args) { MyClass obj = new MyClass (); obj.display(); } }
private-私有访问修饰符
被声明为 private 的方法、变量和构造方法只能被所属类访问,并且类和接口不能声明为 private 。声明为私有访问类型的变量只能通过类中公共的getter 方法被外部类访问。
1 2 3 4 5 6 7 8 9 public class Logger { private String format; public String getFormat () { return this .format; } public void setFormat (String format) { this .format = format; } }
public-公有访问修饰符
被声明为public 的类、方法、构造方法和接口能够被任何其他类访问
1 2 3 public static void main (String[] arguments) { }
protected-受保护的访问修饰符
被 protected 修饰的成员对于本包和其子类可见 :
在碰到涉及protected 成员的调用时,首先要确定出该protected 成员来自何方,其可见性范围是什么,然后就可以判断出当前用法是否可行了
Java protected 关键字详解 | 菜鸟教程 (runoob.com)
Java运算符
算术运算符
操作符
描述
例子
+
加法 - 相加运算符两侧的值
A + B 等于 30
-
减法 - 左操作数减去右操作数
A – B 等于 -10
*
乘法 - 相乘操作符两侧的值
A * B等于200
/
除法 - 左操作数除以右操作数
B / A等于2
%
取余 - 左操作数除以右操作数的余数
B%A等于0
++
自增: 操作数的值增加1
B++ 或 ++B
–
自减: 操作数的值减少1
B– 或 –B
关系运算符
运算符
描述
例子
==
检查如果两个操作数的值是否相等,如果相等则条件为真。
(A == B)为假。
!=
检查如果两个操作数的值是否相等,如果值不相等则条件为真。
(A != B) 为真。
>
检查左操作数的值是否大于右操作数的值,如果是那么条件为真。
(A> B)为假。
<
检查左操作数的值是否小于右操作数的值,如果是那么条件为真。
(A <B)为真。
>=
检查左操作数的值是否大于或等于右操作数的值,如果是那么条件为真。
(A> = B)为假。
<=
检查左操作数的值是否小于或等于右操作数的值,如果是那么条件为真。
(A <= B)为真。
位运算符
操作符
描述
例子
&
如果相对应位都是1,则结果为1,否则为0
(A&B)
|
如果相对应位都是 0,则结果为 0,否则为 1
(A | B)
^
如果相对应位值相同,则结果为0,否则为1
(A ^ B)得到49,即 0011 0001
〜
按位取反运算符翻转操作数的每一位,即0变成1,1变成0。
(〜A)
<<
按位左移运算符。左操作数按位左移右操作数指定的位数。
A << 2
>>
按位右移运算符。左操作数按位右移右操作数指定的位数。
A >> 2
>>>
按位右移补零操作符。左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。
A>>>2
逻辑运算符
操作符
描述
例子
&&
称为逻辑与运算符。当且仅当两个操作数都为真,条件才为真。
(A && B)为假。
| |
称为逻辑或操作符。如果任何两个操作数任何一个为真,条件为真。
(A | | B)为真。
!
称为逻辑非运算符。用来反转操作数的逻辑状态。如果条件为true,则逻辑非运算符将得到false。
!(A && B)为真。
赋值运算符
操作符
描述
例子
=
简单的赋值运算符,将右操作数的值赋给左侧操作数
C = A + B将把A + B得到的值赋给C
+ =
加和赋值操作符,它把左操作数和右操作数相加赋值给左操作数
C + = A等价于C = C + A
- =
减和赋值操作符,它把左操作数和右操作数相减赋值给左操作数
C - = A等价于C = C - A
* =
乘和赋值操作符,它把左操作数和右操作数相乘赋值给左操作数
C * = A等价于C = C * A
/ =
除和赋值操作符,它把左操作数和右操作数相除赋值给左操作数
C / = A,C 与 A 同类型时等价于 C = C / A
(%)=
取模和赋值操作符,它把左操作数和右操作数取模后赋值给左操作数
C%= A等价于C = C%A
<< =
左移位赋值运算符
C << = 2等价于C = C << 2
>> =
右移位赋值运算符
C >> = 2等价于C = C >> 2
&=
按位与赋值运算符
C&= 2等价于C = C&2
^ =
按位异或赋值操作符
C ^ = 2等价于C = C ^ 2
| =
按位或赋值操作符
C | = 2等价于C = C | 2
Java循环结构
while循环
只要布尔表达式为True
;循环就会一直执行下去
demo
1 2 3 4 5 6 7 8 9 10 public class Test { public static void main (String[] args) { int x = 10 ; while ( x < 20 ) { System.out.print("value of x : " + x ); x++; System.out.print("\n" ); } } }
do…while循环
demo
1 2 3 4 5 6 7 8 9 10 11 public class Test { public static void main (String[] args) { int x = 10 ; do { System.out.print("value of x : " + x ); x++; System.out.print("\n" ); }while ( x < 20 ); } }
for循环
demo
1 2 3 4 5 6 7 8 9 public class Test { public static void main (String[] args) { for (int x = 10 ; x < 20 ; x = x+1 ) { System.out.print("value of x : " + x ); System.out.print("\n" ); } } }
Java增强for循环
声明语句 :声明新的局部变量,该变量的类型必须和数组元素的类型匹配。其作用域限定在循环语句中,其值与此时数组元素的值相等
表达式 :表达式是要访问的数组名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class Test { public static void main (String[] args) { int [] numbers = {10 ,20 ,30 ,40 ,50 }; for (int x : number){ System.out.print( x ); System.out.print("," ) } System.out.println("\n" ); String [] name = {"Jam" ,"Lay" ,"Tom" ,"Lacy" } for (String name : names){ System.out.print( name ); System.out.print("," ) } } } # result 10 ,20 ,30 ,40 ,50 ,James,Larry,Tom,Lacy,
break关键字
break
主要用在循环语句或者 switch
语句中,用来跳出整个语句块
demo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class Test { public static void main (String[] args) { int [] numbers = {10 , 20 , 30 , 40 , 50 }; for (int x : numbers ) { if ( x == 30 ) { break ; } System.out.print( x ); System.out.print("\n" ); } } } #result 10 20
continue关键字
continue
适用于任何循环控制结构中。作用是让程序立刻跳转到下一次循环的迭代
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 [] numbers = {10 , 20 , 30 , 40 , 50 }; for (int x : numbers ) { if ( x == 30 ) { continue ; } System.out.print( x ); System.out.print("\n" ); } } } # result 10 20 40 50
Java条件语句
if语句
一个 if
语句包含一个布尔表达式和一条或多条语句 。
demo
1 2 3 4 5 6 7 8 9 10 public class Test { public static void main (String args[]) { int x = 10 ; if ( x < 20 ){ System.out.print("这是 if 语句" ); } } }
if…else语句
if
语句后面可以跟 else
语句,当 if
语句的布尔表达式值为 false
时,else 语句块会被执行 。
1 2 3 4 5 6 if (布尔表达式){ } else { }
demo
1 2 3 4 5 6 7 8 9 10 11 12 public class Test { public static void main (String args[]) { int x = 30 ; if ( x < 20 ){ System.out.print("这是 if 语句" ); }else { System.out.print("这是 else 语句" ); } } }
if…else if…else 语句
if
语句后面可以跟 else if…else
语句,这种语句可以检测到多种可能的情况。
1 2 3 4 5 6 7 8 9 if (布尔表达式 1 ){ }else if (布尔表达式 2 ){ }else if (布尔表达式 3 ){ }else { }
demo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class Test { public static void main (String args[]) { int x = 30 ; if ( x == 10 ){ System.out.print("Value of X is 10" ); }else if ( x == 20 ){ System.out.print("Value of X is 20" ); }else if ( x == 30 ){ System.out.print("Value of X is 30" ); }else { System.out.print("这是 else 语句" ); } } }
嵌套的 if…else 语句
你可以在另一个 if
或者 else if
语句中使用 if
或者 else if
语句
1 2 3 4 5 6 if (布尔表达式 1 ){ if (布尔表达式 2 ){ } }
demo
1 2 3 4 5 6 7 8 9 10 11 12 13 public class Test { public static void main (String args[]) { int x = 30 ; int y = 10 ; if ( x == 30 ){ if ( y == 10 ){ System.out.print("X = 30 and Y = 10" ); } } } }
Java switch case 语句
switch case
语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支
1 2 3 4 5 6 7 8 9 10 11 switch (expression){ case value : break ; case value : break ; default : }
switch case 执行时,一定会先进行匹配,匹配成功返回当前 case 的值,再根据是否有 break,判断是否继续输出,或是跳出判断
demo
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 public class Test { public static void main (String args[]) { char grade = 'C' ; switch (grade) { case 'A' : System.out.println("优秀" ); break ; case 'B' : case 'C' : System.out.println("良好" ); break ; case 'D' : System.out.println("及格" ); break ; case 'F' : System.out.println("你需要再努力努力" ); break ; default : System.out.println("未知等级" ); } System.out.println("你的等级是 " + grade); } }
Java数组
声明数组变量
1 2 3 dataType[] arrayRefVar; eg: double [] mylist
创建数组
使用 dataType[arraySize] 创建了一个数组
把新创建的数组的引用赋值给变量 arrayRefVar
1 arrayRefVar = new dataType [arraysize]
demo
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 voud 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("totla is : " + total); } }
处理数组
数组的元素类型和数组的大小都是确定的,所以当处理数组元素时候,我们通常使用基本循环 或者 For-Each 循环。
demo
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 class TestArray { public static void main (String[] args) { double [] mylist = {1.1 ,1.2 ,1.3 ,1.4 }; for (int i = 0 ;i < mylist.length; i++){ System.out.println(mylist[i] + " " ); } double total = 0 ; for (int i = 0 ;i < mylist.length;i++){ total += mylist[i]; } System.out.print("Total is : " + total); double max = mylist[0 ]; for (int i = 0 ;i < mylist.length;i++){ if (mylist[i] > max){ max = mylist[i]; } } System.out.println("The Max is : " + max); } }
For-Each 循环
For-Each 循环或者加强型循环,它能在不使用下标的情况下遍历数组。
语法格式如下:
1 2 3 4 for (type element: array){ System.out.println(element); }
demo
1 2 3 4 5 6 7 8 9 10 11 public class TestArray { public static void main (String[] args) { double [] mylist = {1.2 ,1.3 ,1.4 ,1.5 ,1.6 }; for (double element : mylist){ System.out.println(element); } } }
数组作为函数的参数
数组可以直接作为参数传递给方法
demo
1 2 3 4 5 public static void printArray (int [] array) { for (int i = 0 ;i < array.length;i++){ System.out.println(array[i] + " " ); } }
数组作为函数的返回值
1 2 3 4 5 6 7 8 public static int [] reverse(int [] list){ int [] result = new int [list.length]; for (int i = 0 ,j = result.length - 1 ;i < list.length;i++,j--){ result[j] = result[i]; } retuen result; }
多维数组
多维数组可以看作是数组的数组,一个二维数组就是一个特殊的一维数组;其中的每一个元素都是一个一维数组
1 String[][] str = new String [3 ][4 ]
多维数组的动态初始化(以二维数组为例)
1 type[][] typeName = new type [typeLength1][typeLength2];
二维数组 a 可以看成一个两行三列的数组
demo
1 2 3 4 5 6 7 8 9 String[][] s = new String [2 ][3 ] S[0 ] = new String [2 ]; s[1 ] = new String [3 ]; s[0 ][0 ] = new String ("Good" ); s[0 ][1 ] = new String ("Luck" ); s[1 ][0 ] = new String ("to" ); s[1 ][1 ] = new String ("you" ); s[1 ][2 ] = new String ("!" );
s[0]=new String[2] 和 s[1]=new String[3] 是为最高维分配引用空间,也就是为最高维限制其能保存数据的最长的长度,然后再为其每个数组元素单独分配空间s0=new String(“Good”) 等操作
多维数组的引用(以二维数组为例)
对二维数组中的每个元素,引用方式为arayName[index1][index2]
Java正则表达式
正则表达式语法
在Java
中\\
表示我要插入一个正则表达式的反斜线;使其后面的符号具有特殊的意义
1 2 System.out.print("\\" ); System.out.print("\\\\" );
字符
说明
\
将下一字符标记为特殊字符、文本、反向引用或八进制转义符。例如, n 匹配字符 n 。\n 匹配换行符。序列 \\ 匹配 \ ,\( 匹配 **(**。
^
匹配输入字符串开始的位置。如果设置了 RegExp 对象的 Multiline 属性,^ 还会与”\n”或”\r”之后的位置匹配。
$
匹配输入字符串结尾的位置。如果设置了 RegExp 对象的 Multiline 属性,$ 还会与”\n”或”\r”之前的位置匹配。
*
零次或多次匹配前面的字符或子表达式。例如,zo* 匹配”z”和”zoo”。* 等效于 {0,}。
+
一次或多次匹配前面的字符或子表达式。例如,”zo+”与”zo”和”zoo”匹配,但与”z”不匹配。+ 等效于 {1,}。
?
零次或一次匹配前面的字符或子表达式。例如,”do(es)?”匹配”do”或”does”中的”do”。? 等效于 {0,1}。
{n }
n 是非负整数。正好匹配 n 次。例如,”o{2}”与”Bob”中的”o”不匹配,但与”food”中的两个”o”匹配。
{n ,}
n 是非负整数。至少匹配 n 次。例如,”o{2,}”不匹配”Bob”中的”o”,而匹配”foooood”中的所有 o。”o{1,}”等效于”o+”。”o{0,}”等效于”o*”。
{n ,m }
m 和 n 是非负整数,其中 n <= m 。匹配至少 n 次,至多 m 次。例如,”o{1,3}”匹配”fooooood”中的头三个 o。’o{0,1}’ 等效于 ‘o?’。注意:您不能将空格插入逗号和数字之间。
?
当此字符紧随任何其他限定符(*、+、?、{n }、{n ,}、{n ,m })之后时,匹配模式是”非贪心的”。”非贪心的”模式匹配搜索到的、尽可能短的字符串,而默认的”贪心的”模式匹配搜索到的、尽可能长的字符串。例如,在字符串”oooo”中,”o+?”只匹配单个”o”,而”o+”匹配所有”o”。
.
匹配除”\r\n”之外的任何单个字符。若要匹配包括”\r\n”在内的任意字符,请使用诸如”[\s\S]”之类的模式。
(pattern )
匹配 pattern 并捕获该匹配的子表达式。可以使用 $0…$9 属性从结果”匹配”集合中检索捕获的匹配。若要匹配括号字符 ( ),请使用”(“或者”)“。
(?:pattern )
匹配 pattern 但不捕获该匹配的子表达式,即它是一个非捕获匹配,不存储供以后使用的匹配。这对于用”or”字符 (|) 组合模式部件的情况很有用。例如,’industr(?:y|ies) 是比 ‘industry|industries’ 更经济的表达式。
(?=pattern )
执行正向预测先行搜索的子表达式,该表达式匹配处于匹配 pattern 的字符串的起始点的字符串。它是一个非捕获匹配,即不能捕获供以后使用的匹配。例如,’Windows (?=95|98|NT|2000)’ 匹配”Windows 2000”中的”Windows”,但不匹配”Windows 3.1”中的”Windows”。预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。
(?!pattern )
执行反向预测先行搜索的子表达式,该表达式匹配不处于匹配 pattern 的字符串的起始点的搜索字符串。它是一个非捕获匹配,即不能捕获供以后使用的匹配。例如,’Windows (?!95|98|NT|2000)’ 匹配”Windows 3.1”中的 “Windows”,但不匹配”Windows 2000”中的”Windows”。预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。
x |y
匹配 x 或 y 。例如,’z|food’ 匹配”z”或”food”。’(z|f)ood’ 匹配”zood”或”food”。
[xyz ]
字符集。匹配包含的任一字符。例如,”[abc]”匹配”plain”中的”a”。
[^xyz ]
反向字符集。匹配未包含的任何字符。例如,”[^abc]”匹配”plain”中”p”,”l”,”i”,”n”。
[a-z ]
字符范围。匹配指定范围内的任何字符。例如,”[a-z]”匹配”a”到”z”范围内的任何小写字母。
[^a-z ]
反向范围字符。匹配不在指定的范围内的任何字符。例如,”[^a-z]”匹配任何不在”a”到”z”范围内的任何字符。
\b
匹配一个字边界,即字与空格间的位置。例如,”er\b”匹配”never”中的”er”,但不匹配”verb”中的”er”。
\B
非字边界匹配。”er\B”匹配”verb”中的”er”,但不匹配”never”中的”er”。
\cx
匹配 x 指示的控制字符。例如,\cM 匹配 Control-M 或回车符。x 的值必须在 A-Z 或 a-z 之间。如果不是这样,则假定 c 就是”c”字符本身。
\d
数字字符匹配。等效于 [0-9]。
\D
非数字字符匹配。等效于 [^0-9]。
\f
换页符匹配。等效于 \x0c 和 \cL。
\n
换行符匹配。等效于 \x0a 和 \cJ。
\r
匹配一个回车符。等效于 \x0d 和 \cM。
\s
匹配任何空白字符,包括空格、制表符、换页符等。与 [ \f\n\r\t\v] 等效。
\S
匹配任何非空白字符。与 [^ \f\n\r\t\v] 等效。
\t
制表符匹配。与 \x09 和 \cI 等效。
\v
垂直制表符匹配。与 \x0b 和 \cK 等效。
\w
匹配任何字类字符,包括下划线。与”[A-Za-z0-9_]”等效。
\W
与任何非单词字符匹配。与”[^A-Za-z0-9_]”等效。
\xn
匹配 n ,此处的 n 是一个十六进制转义码。十六进制转义码必须正好是两位数长。例如,”\x41”匹配”A”。”\x041”与”\x04”&”1”等效。允许在正则表达式中使用 ASCII 代码。
*num*
匹配 num ,此处的 num 是一个正整数。到捕获匹配的反向引用。例如,”(.)\1”匹配两个连续的相同字符。
*n*
标识一个八进制转义码或反向引用。如果 *n* 前面至少有 n 个捕获子表达式,那么 n 是反向引用。否则,如果 n 是八进制数 (0-7),那么 n 是八进制转义码。
*nm*
标识一个八进制转义码或反向引用。如果 *nm* 前面至少有 nm 个捕获子表达式,那么 nm 是反向引用。如果 *nm* 前面至少有 n 个捕获,则 n 是反向引用,后面跟有字符 m 。如果两种前面的情况都不存在,则 *nm* 匹配八进制值 nm ,其中 n 和 m 是八进制数字 (0-7)。
\nml
当 n 是八进制数 (0-3),m 和 l 是八进制数 (0-7) 时,匹配八进制转义码 nml 。
\un
匹配 n ,其中 n 是以四位十六进制数表示的 Unicode 字符。例如,\u00A9 匹配版权符号 (©)。
java.util.regex包
java.util.regex 包是 Java 标准库中用于支持正则表达式操作的包。
java.util.regex 包主要包括以下三个类:
Pattern类 :pattern
对象是一个正则表达式的编译表示;该方法接受一个正则表达式作为它的第一个参数
Matcher 类: Matcher 对象是对输入字符串进行解释和匹配操作的引擎
PatternSyntaxException: PatternSyntaxException
是一个非强制异常类,它表示一个正则表达式模式中的语法错误。
demo
以下实例中使用了正则表达式 .*runoob.* 用于查找字符串中是否包了 runoob 子串:
1 2 3 4 5 6 7 8 9 10 11 12 import java.util.regex.*;class RegexExample { 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("String including the 'runoob' ? " + isMatch); } }
捕获组
捕获组是把多个字符当一个单独单元进行处理的方法,它通过对括号内的字符分组来创建。
可以通过调用 matcher 对象的 groupCount 方法来查看表达式有多少个分组。groupCount 方法返回一个 int 值,表示matcher对象当前有多个捕获组。
还有一个特殊的组(group(0)),它总是代表整个表达式。该组不包括在 groupCount 的返回值中。
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 import java.util.regex.Matcher;import java.util.regex.Pattern; public class RegexMatches { public static void main ( String[] args ) { String line = "This order was placed for QT3000! OK?" ; String pattern = "(\\D*)(\\d+)(.*)" ; Pattern r = Pattern.compile(pattern); Matcher m = r.matcher(line); System.out.println("The groupCount is : " + m.groupCount()); if (m.find( )) { System.out.println("Found value: " + m.group(0 ) ); System.out.println("Found value: " + m.group(1 ) ); System.out.println("Found value: " + m.group(2 ) ); System.out.println("Found value: " + m.group(3 ) ); } else { System.out.println("NO MATCH" ); } } }
start 和 end 方法
下面是一个对单词 “cat” 出现在输入字符串中出现次数进行计数的例子
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 import java.util.regex.Matcher;import java.util.regex.Pattern;public class RegexMathes { private static final String REGEX = "\\bcat\\b" ; private static final String INPUT = "cat cat cat cattie cat" ; public static void main (String[] args) { Pattern p = Pattern.compile(REGEX); Matcher m = p.matcher(INPUT); int count = 0 ; while (m.find()){ count++; System.out.println("Match number " + count); System.out.println("Match number " + m.start()); System.out.println("Match number " + m.end()); } } } # result Match number 1 start(): 0 end(): 3 Match number 2 start(): 4 end(): 7 Match number 3 start(): 8 end(): 11 Match number 4 start(): 19 end(): 22
可以看到这个例子是使用单词边界,以确保字母"c" "a" "t"
并非仅是一个较长的词的子串。它也提供了一些关于输入字符串中匹配发生位置的有用信息。
Start
方法返回在以前的匹配操作期间,由给定组所捕获的子序列的初始索引,end
方法最后一个匹配字符的索引加 1。
Java方法
此时我们先从System.out.print()
说起:
**print()**:print()
是一个方法
System :System
是系统类
out :out
是输出对象
此时这句话的作用就是调用系统类System中的输出对象out中的方法print()
方法的定义
1 2 3 4 5 6 修饰符 返回值类型 方法名(参数类型 参数名){ ... 方法体 ... return 返回值; }
修饰符: 修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。
返回值类型 : 方法可能会返回值。returnValueType 是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType 是关键字void 。
方法名: 是方法的实际名称。方法名和参数表共同构成方法签名。
参数类型: 参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
方法体: 方法体包含具体的语句,定义该方法的功能。
demo
1 2 3 4 5 6 7 8 9 public static int max (int num1,int num2) { int result; if (num1 > num2) result = num1; else result = num2; return result; }
方法的调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class TestMax { public static void main (String[] args) { int i = 5 ; int j = 2 ; int k = max(i,j); System.out.print(i + " 和 " + j + " 比较,最大值是:" + k) } public static int max (int num1,int num2) { int result; if (num1 > num2) result = num1; else result = num2; return result; } }
Void关键字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class TestVoidMethod { public static void main (String[] args) { printGrade(78.5 ); } public static void printGrade (double score) { if (score >= 90.0 ) { System.out.println('A' ); } else if (score >= 80.0 ) { System.out.println('B' ); } else if (score >= 70.0 ) { System.out.println('C' ); } else if (score >= 60.0 ) { System.out.println('D' ); } else { System.out.println('F' ); } } }
构造方法
当一个对象被创建时候,构造方法用来初始化该对象。构造方法和它所在类的名字相同,但构造方法没有返回值。
下面是一个使用构造方法的例子
1 2 3 4 5 6 7 8 9 class myclass { int x; myclass(){ x = 10 ; } }
下面是一个调用构造方法来初始化一个对象
1 2 3 4 5 6 7 public class ConsDemo { public static void main (String[] args) { myclass t1 = new myclass (); myclass t2 = new myclass (); System.out.println(t1.x + " " + t2.x) } }
Java Stream、File、IO
Java.io
包几乎包含了所有操作输入、输出需要的类。所有这些流类代表了输入源和输出目标。
Java.io
包中的流支持很多种格式,比如:基本类型、对象、本地化字符集等等。
一个流可以理解为一个数据的序列。输入流表示从一个源读取数据,输出流表示向一个目标写数据。
Java
为 I/O
提供了强大的而灵活的支持,使其更广泛地应用到文件传输和网络编程中。
从控制台读取多字符输入
Java
的控制台输入由 System.in
完成。
为了获得一个绑定到控制台的字符流,你可以把 System.in
包装在一个 BufferedReader
对象中来创建一个字符流。
下面是创建 BufferedReader
的基本语法:
1 BufferedReader br = new BufferedReader (new InputStreamReader (System.in));
BufferedReader
对象创建后,我们便可以使用 read()
方法从控制台读取一个字符,或者用 readLine()
方法读取一个字符串。
demo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.io.*; public class BRRead { public static void main (String[] args) throws IOException { char c; BufferedReader br = new BufferedReader (new InputStreamReader (System.in)); System.out.println("输入字符, 按下 'q' 键退出。" ); do { c = (char ) br.read(); System.out.println(c); } while (c != 'q' ); } }
从控制台读取字符串
从标准输入读取一个字符串需要使用 BufferedReader 的 readLine()
方法。
它的一般格式是:
1 String readLine ( ) throws IOException
demo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import java.io.*; public class BRReadLines { public static void main (String[] args) throws IOException { BufferedReader br = new BufferedReader (new InputStreamReader (System.in)); String str; System.out.println("Enter lines of text." ); System.out.println("Enter 'end' to quit." ); do { str = br.readLine(); System.out.println(str); } while (!str.equals("end" )); } }
控制台输出
在此前已经介绍过,控制台的输出由 print( ) 和 println()
完成。这些方法都由类 PrintStream
定义,System.out
是该类对象的一个引用。
PrintStream
继承了 OutputStream
类,并且实现了方法 write()
。这样,write()
也可以用来往控制台写操作。
PrintStream
定义 write()
的最简单格式如下所示:
demo
1 2 3 4 5 6 7 8 9 10 11 import java.io.*; public class WriteDemo { public static void main (String[] args) { int b; b = 'A' ; System.out.write(b); System.out.write('\n' ); } }
读写文件
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 import java.io.*;public class fileStreamTest { public static void main (String[] args) throws IOException{ File f = new File ("a.txt" ); FileOutputStream fop = new FileOutputStream (f); OutputStreamWriter writer = new OutputStreamWriter (fop,"UTF-8" ); writer.append("中文输入" ); writer.append("\r\n" ); writer.append("English" ); fop.close(); FileInputStream fip = new FileInputStream (f); InputStreamReader reader = new InputStreamReader (fip, "UTF-8" ); StringBuffer sb = new StringBuffer (); while (reader.ready()){ sb.append((char ) reader.read()); } System.out.println(sb.toString()); reader.close(); fip.close(); } }
文件和I/O
Java File类
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 25 26 27 28 29 30 31 32 33 import java.io.File; public class DirList { public static void main (String args[]) { String dirname = "/java" ; File f1 = new File (dirname); if (f1.isDirectory()) { System.out.println("Directory of " + 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] + " is a directory" ); } else { System.out.println(s[i] + " is a file" ); } } } else { System.out.println(dirname + " is not a directory" ); } } } #result Directory of /java bin is a directory lib is a directory demo is a directory test.txt is a file README is a file index.html is a file include is a directory
Java FileReader类
FileReader
类从InputStreamReader
类继承而来。该类按字符读取流中数据。
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 import java.io.*; public class FileRead { public static void main (String args[]) throws IOException { File file = new File ("Hello1.txt" ); file.createNewFile(); FileWriter writer = new FileWriter (file); writer.write("This\n is\n an\n example\n" ); writer.flush(); writer.close(); FileReader fr = new FileReader (file); char [] a = new char [50 ]; fr.read(a); for (char c : a) System.out.print(c); fr.close(); } } # result This is an example
Java FileWriter类
FileWriter
类从 OutputStreamWriter
类继承而来。该类按字符向流中写入数据
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 import java.io.*; public class FileWrite { public static void main (String args[]) throws IOException { File file = new File ("Hello1.txt" ); file.createNewFile(); FileWriter writer = new FileWriter (file); writer.write("This\n is\n an\n example\n" ); writer.flush(); writer.close(); FileReader fr = new FileReader (file); char [] a = new char [50 ]; fr.read(a); for (char c : a) System.out.print(c); fr.close(); } } #result This is an example
Java中的目录
创建目录:
File类中有两个方法可以用来创建文件夹:
**mkdir( )**方法创建一个文件夹,成功则返回true,失败则返回false。失败表明File对象指定的路径已经存在,或者由于整个路径还不存在,该文件夹不能被创建。
**mkdirs()**方法创建一个文件夹和它的所有父文件夹。
demo
1 2 3 4 5 6 7 8 9 10 11 12 13 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(); } } #result 编译并执行上面代码来创建目录 "/tmp/user/java/bin" 。
读取目录
一个目录其实就是一个 File 对象,它包含其他文件和文件夹。
如果创建一个 File 对象并且它是一个目录,那么调用 isDirectory()
方法会返回 true
。
可以通过调用该对象上的 list()
方法,来提取它包含的文件和文件夹的列表。
下面展示的例子说明如何使用 list()
方法来检查一个文件夹中包含的内容:
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.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 + " 不是一个目录" ); } } } #result 目录 /tmp bin 是一个目录 lib 是一个目录 demo 是一个目录 test.txt 是一个文件 README 是一个文件 index.html 是一个文件 include 是一个目录
删除目录或文件
删除文件可以使用 java.io.File.delete() 方法。
以下代码会删除目录 /tmp/java/,需要注意的是当删除某一目录时, 必须保证该目录下没有其他文件才能正确删除 ,否则将删除失败。
测试目录结构
1 2 3 4 /tmp/java/ |-- 1. log |-- test
demo
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(); } }