public class FirstSample {
public static void main(String[] args)
{
System.out.println("Hello World");
}
}
对于上述代码,我们需要注意以下几点:
public为访问修饰符,class后面跟的是类名,关于类名的命名方法,推荐 驼峰命名法,例如FirstSample、CamelCase
类名的首字母一般是大写。
源代码的文件名必须与公共类相同,且用.java作为拓展名,Java编译器会将上述字节码文件自动地命名为FirstSample.java
当使用
java ClassName
运行已经编译的程序时,Java虚拟机将从指定类中的main方法开始执行,我们需要知道,每个java代码都必须有一个main方法,声明方法如下
public class ClassName{
public static void main(String[] args){
program statements
}
}
接下来我们分析以下语句
{
System.out.println("Hello World");
}
在这里使用了System.out对象调用了println方法。注意,点号(.)用于调用方法。Java的调用方法为
object.method(parameters)
注释主要分为以下三种
// 用于单行注释
/* */用于长篇注释
/**
*/这种用于自动生成文档
注意:Java代码中的 /* */ 注释不能嵌套,不能用这对符号直接将代码括起来当作注释,因为代码中可能包含 */
基本数据类型和引用数据类型的区别主要在于:
基本类型变量在栈,引用类型变量引用在堆。
赋值时,基本数据类型复制的是值,引用数据变量复制的是引用。
四种数据类型:
类型 | 占用存储空间 | 表示范围 |
---|---|---|
byte | 1字节 | -128~127 |
short | 2字节 | -2^15 ~ 2^15-1 |
int | 4字节 | -2^31 ~ 2^31-1 |
long | 8字节 | -2^63 ~ 2^63-1 |
java提供了四种整型变量,包括int short long byte,我们需要注意以下几点
长整型后有一个后缀L或l(例如4000000000L).十六进制有0X或0x做前缀。八进制有一个0作为前缀(例如010表示8),但容易混淆
可以使用0b或者0B写二进制数,也可以为数字位加下划线100_000_000
Java没有无符号(unsigned)的整型,可以用long来处理。
java提供了两种浮点型变量,包括float double,我们需要注意以下几点
float类型的数值后面有一个F或f作为后缀,没有后缀的默认为double类型
double类型的数值后面有一个D或d作为后缀
浮点数计算的出错表示为以下三个特殊的浮点值
正无穷大
负无穷大
NaN(不是一个数字)
这三个特殊的值分别表示为Double.POSITIVE_INFINITY、Double.NEGATIVE_INFINITY和Double.NaN,特别说明,不能检测一个特定值是否等于Double.NaN:
if(x==Double.NaN) //is never true
所有非数值的值都是因为不相同的,然而,可以使用Double.NaN方法
if(Double.isNaN(x)) //check whether x is "not a number"
同时,我们要注意两个浮点数不能直接比较大小,我们可以利用以下方式比较
Double.doubleToLongBits(num1) == Double.doubleToLongBits(num2)
Java字符采用Unicode编码,每个字符占用两个字节。
特殊字符的转义序列
转义序列 | 名称 | Unicode值 |
---|---|---|
\b | 推格 | \u0008 |
\t | 制表 | \u0009 |
\n | 换行 | \u000a |
\r | 回车 | \u000d |
\“ | 双引号 | \u0022 |
’ | 单引号 | \u0027 |
\ | 反斜杠 | \u005c |
Unicode转义序列会在解析代码之前进行处理,故可能发生以下错误:
“\u0022+\u0022"会变为”"+""
要注意注释中的\u,例如:
// \u00A0 is a newline
会产生一个错误,因为\u00A0会替换为一个换行符
类似的
// Look inside C:\users
会产生一个错误,因为\u后面不是十六进制数
提示:如果想知道那些Unicode字符属于Java中的“字母”,可以使用Character类的以下两种方法
Character.isJavaIdentifierStart(char ch/int codePoint)
Character.isJavaIdentifierPart(char ch/int codePoint)
相关语法可以类比C\C++,在这里主要强调java不区分声明与定义,例如:
int a = 10; //这是一个定义
extern int i; //这是一条声名
在java中用final表示常量
public class FirstSample{
public static void main(String[] args){
final int A = 10;
}
}
final表示这个常量只能被赋值一次,习惯上常量名使用全大写
相关语法可以类比C\C++
由于浮点数的计算存在精度问题,那么有strictfp关键字解决,如果将一个类标记为strictpf,那么这个类中的所有方法要使用严格的浮点计算
在Math类中,包含了各种各样的方法。例如以下程序:
double x=4;
double y=Math.sqrt(x);
在Math类中,提供了一些基本的函数:
Math.sin(10)
Math.cos(10)
Math.tan(10)
Math.atan(10)
Math.atan2(10)
Math.exp(10)
Math.log(10)
Math.log10(10)
Math.E
Math.Pi
floorMod方法的目的是解决整数余数的问题
下图表示数值类型之间的合法转换,实心箭头表示精度不会损失,虚线箭头表示会有精度损失
在进行计算时,需要把操作数转换成同一种类型,然后再进行计算
如果两个操作数中有一个是double类型,另一个操作数会被转换成double类型
否则,如果两个操作数中有一个是float类型,另一个操作数会被转换成float类型
否则,如果两个操作数中有一个是long类型,另一个操作数会被转换成long类型
否则,两个操作数都会转换成int类型
以下为示例程序:
int x = 10;
double y = (double) x;
但要注意,不要超过目标类型的范围
例如+=、-=等
例如++、–等
例如==、!=、<=等
位运算符主要有以下几种:
&,|,^,~,>>,<<,>>>
不在此过多阐述,自行百度
有时候,变量的取值只在一个有限的集合内。例如:销售的服装或比萨饼只有小、中、大和超大这四种尺寸。当然,可以将这些尺寸分别编码为1、2、3、4或S、M、L、X。但这样存在着一定的隐患。在变量中很可能保存的是一个错误的值 (如0或m)。针对这种情况,可以自定义枚举类型。枚举类型包括有限个命名的值。例如:
enum Size { SMALL, MEDIUM, LARGE, EXTRA _LARGE };
现在,可以声明这种类型的变量:
Size S = Size.MEDIUM;
Size类型的变量只能存储这个类型声明中给定的某个枚举值,或者null值,null 表示这个变量没有设置任何值
从概念上讲,Java字符串就是Unicode字符序列。例如,串“Java\u2122"由5个Unicode字符J、a、v、a和T。Java没有内置的字符串类型,而是在标准Java类库中提供了一个预定义类,很自然地叫做String。每个用双引号括起来的字符串都是String类的个实例:
String e=""; // an empty string
String greeting = "Hello" ;
String类的 substring(a,b) 方法可以从一一个较大的字符串提取出一个子串。例如:
String greeting= "He11o";
String S = greeting. substring(0, 3);
创建了一个由字符“Hel” 组成的字符串。字符串长度为b-a
与绝大多数的程序设计语言一样,Java语言允许使用+号连接
String expletive = "Expletive";
String PCI3 = "deleted";
String message = expletive + PCI3;
上述代码将“Expledetear”赋给变量message (注意,单词之间没有空格+号按照给定的次序将两个字符串拼接起来)。
当将一个字符中与一个非字符串的值进行拼接时,后者被转换成字符串(在第5章中可以看到,任何一个Java对象都可以转换成字符串)。例如:
int age = 13;
String rating =“PG” + age;
rating设置为“PG13”
这种特性通常用在输出语句中。例如:
System. out,printn("The answer is " + answer);
这是一条合法的语句,并且将会打印出所希望的结果(因为单词is后面加了一一个空格,输出时也会加上这个空格)。
如果需要把多个字符串放在一起,用个定界符分隔,可以使用静态join方法:
String all = String.join(" /","S", "M", "L", "XL");
//all is the string "S/M/L/XL"
由于不能修改Java字符串中的字符,所以在Java文档中将Stirng类对象称为不可变字符串,不同于在C/C++中,字符串被认为是字符型数组,Java中字符串大致类似于char*指针。但是如果我们想将字符串“Hello!”转换为“Help!”,我们可以使用以下方法:
String str="hello!";
str=str.substring(0,3)+"p!";
可以使用equals方法检测两个字符串是否相等。对于表达式
s.eaquls(t);
如果字符串s与字符串t相等,则返回true;否则,返回false。需要注意,s与t可以是字符串变量,也可以是字符串字面变量,例如,下列表达式是合法的
"Hello".equals(greeting);
如果想要检测两个字符串大小是否是否相等,而不区分大小写,可以使用equalsIgnoreCase方法
"Hello".equalsIgnoreCase("HELLO");
注意:尽可能不要使用==判断两个字符串是否相等
空串“”是长度为0的字符事。可以调用以下代码检查一个字符串是否为空:
if (str.length() == 0)
或
if (str.equals(""))
空串是一个Java对象,有自己的串长度 (0) 和内容 (空)。不过,String变量还可以存放一个特殊的值,名为null,这表示目前没有任何对象与该变量关联。要检查一个字符串是否为null,要使用以下条件:
if (str == null)
有时要检查一个字符串既不是null也不为空串,这种情况下就需要使用以下条件:
if (str != null && str.length() != 0)
首先要检查str不为null。如果在一个null值上调用方法,会出现错误。
Java字符串由char值序列组成。从1.3.3 节“char类型”已经看到,char数据类型是一个采用UTF-16编码表示Unicode码点的代码单元。大多数的常用Unicode字符使用个代码单元就可以表示,而辅助字符需要一对代码单元表示。
length方法将返回采用UTF- 16编码表示的给定字符串所需要的代码单元数量。例如:
String greeting = "Hello";
int n = greeting.length(); // is 5.
要想得到实际的长度,即码点数量,可以调用:
int cpCount = greeting.codePointCount(0, greeting.length());
调用 s.charAt(n) 将返回位置n的代码单元,n介于0 ~ s.length()-1之间。例如:
char first = greeting.charAt(0); // first is 'H'
char last = greeting.charAt(4); // last is 'o'
要想得到第i个码点,应该使用下列语句
int index = greeting.offsetByCodePoints(0, i);
int cp = greeting.codePointAt(index);
让浏览器指向安装JDK的docs/api/index.html子目录即可
有些时候,需要由较短的字符串构建字符串,例如,按键或来自文件中的单词。采用字符串连接的方式达到此目的的效率又比较低。每次连接字符串,都会构建一个新的String对象,既耗时,又浪费空间。使用StringBuilder类就可以避免这个问题的发生。
如果需要用许多小段的字符串构建个字符串,那么应该按照下列步骤进行。首先,构建一个空的字符串构建器:
StringBuilder builder = new StringBuilder();
当每次需要添加一部分内容时,就调用append方法。
builder.append(ch); // appends s a single character
builder.append(str); // appends a string
在需要构建字符串时就调用toString方法,将可以得到一个String对象,其中包含了构建器中的字符序列
String completedString = builder.toString();
要想使用Scanner,我们首先要添加以下语句
import java.util.Scanner;
想要通过控制台输入,首先要构建Scanner对象,并与“标准输入流”System.in关联。点击此处了解Java Scanner类
Scanner in = new Scanner(System.in)
现在,就可以使用Scanner类的各种方法实现输人操作了。例如,nextLine方法将输人一行。
System.out.print("What is your name? ");
String name = in.nextLine();
在这里,使用nextLine方法是因为在输人行中有可能包含空格。要想读取一个单词 (以空白符作为分隔符) ,就调用
String firstName = in.next();
要想读取一一个整数,就调用nextInt方法。
System.out.print("How old are you? ");
int age = in.nextInt();
与此类似,要想读取下一个浮点数,就调用nextDouble方法。
在程序清单1-2的程序中,询问用户姓名和年龄,然后打印一条如下格式的消息:Hello, Cay. Next year, you’ll be 57
最后,在程序的最开始添加上一行:
import java.util.*;
Scanner类定义在java.util包中。当使用的类不是定义在基本java.lang包中时,一定要使用import指示字将相应的包加载进来。
public class Test {
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
System.out.print("What's you name");
String name = in.nextLine();
System.out.print("How old are you");
int age = in.nextInt();
System.out.print("Hello,"+name+".Next year , you'll be"+ (age+1));
}
}
因为输入是可见的,所以Scanner类不适合从控制台读取密码。Java SE 6特别引入了Console类来实现这个目的。想要读取一个密码,可以使用以下代码:
Console cons = System.console();
String username = cons.readline("User name:");
char[] passwd = cons.readPassword("Password");
为了安全起见,返回的密码存放在一维字符数组中,而不是字符串中。在对密码进行处理之后,应该马上用一个填充值覆盖数组元素。
采用Console对象处理输入不如采用Scanner方便。每次只能读取一-行输入,而没有能够读取一个单词或一个数值的方法。
在这里使用到了java.io包
System.in.read();
System.out.print();
以下是基本语法
char c=' ';
System.out.print("Please input a char:");
try{
c = (char) System.in.read();
}catch(IOException e){}
System.out.println("You have entered:"+c);
在以上语句中只能获取一个字符输入。如果我们想获取多个字符输入,就需要以下方式
public class AppLineInOut {
public static void main(String[] args){
String a = null;
System.out.print("Please input a string:");
try{
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
a=in.readLine();
}catch(IOException e){}
System.out.printf("You have entered: %s",a);
}
}
我们可以使用以下方式来将输入的字符串解析成数字
public class AppNumInOut {
public static void main(String[] args){
String a = null;
System.out.print("Please input a string:");
try{
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
a=in.readLine();
n=Integer.parseInt(a); //又有Double.parseDouble();
}catch(IOException e){}
System.out.printf("You have entered: %s",a);
}
}
Java SE 5.0沿用了C语言库中的printf方法。 我们可以使用以下语句作为参考:
System.out.printf("You have entered: %s",a);
我们以设计一个简单的平方计算器为例子:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Example {
public static void main(String[] args){
new AppFrame();
}
}
class AppFrame extends JFrame
{
JTextField in = new JTextField(10);
JButton btn = new JButton("求平方");
JLabel out = new JLabel("用于显示结果的标签");
public AppFrame()
{
setLayout(new FlowLayout()); //setLayout设置布局
getContentPane().add(in);
getContentPane().add(btn);
getContentPane().add(out);
btn.addActionListener(new BtnActionAdapter());
setSize(400,100);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setVisible(true);
}
class BtnActionAdapter implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String s = in.getText();
double d = Double.parseDouble(s); //将输入解析成浮点数
double sq=d*d;
out.setText(d+"的平方是"+sq);
}
}
}
当然,为了达到简化的目的,我们也可以使用Lambda表达式:
public class Example {
public static void main(String[] args){
new AppFrame();
}
}
class AppFrame extends JFrame
{
JTextField in = new JTextField(10);
JButton btn = new JButton("求平方");
JLabel out = new JLabel("用于显示结果的标签");
public AppFrame()
{
setLayout(new FlowLayout());
getContentPane().add(in);
getContentPane().add(btn);
getContentPane().add(out);
btn.addActionListener(e->{
String s = in.getText();
double d = Double.parseDouble(s);
double sq=d*d;
out.setText(d+"的平方是"+sq);
});
setSize(400,100);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setVisible(true);
}
}
public class App extends JApplet{
public static void main(String[] args){
JFrame frame = new JFrame();
APP app = new App();
app.init();
frame.getContentPane().add(app);
frame.setSize(400,100);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
}
JTextField in = new JTextField(10);
JButton btn = new JButton("求平方");
JLabel out = new JLabel("用于显示结果的标签");
public void init()
{
setLayout(new FlowLayout());
add(in);
add(btn);
add(out);
btn.addActionListener(e->{
String s = in.getText();
double d = Double.parseDouble(s);
double sq=d*d;
out.setText(d+"的平方是"+sq);
});
}
}
要想对文件进行读取,就需要一个用File对象构造的一个Scanner对象,例如:
Scanner in = new Scanner(Paths.get("myfile.txt"),"UTF-8");
如果文件名中包含反斜杠符号,就要记住在每个反斜杠之前再额外加一个反斜杠:“c:\ \mydirectory\ \myfile.txt”
要想写入文件,就需要构造的一个PrintWriter对象,在构造机中,只需要提供文件名:
PrintWriter out = new PrintWriter("myfile.txt","UTF-8");
正如读者所看到的,访问文件与使用System.in和System.out一样容易。要记住一点:如果用一个不存在的文件构造一个Scanner,或者用一个不能被创建的文件名构造一个PrintWriter,那么就会发生异常。Java编译器认为这些异常比“被零除”异常更严重。之后将会学习各种处理异常的方式。现在,应该告知编译器:已经知道有可能出现“输入/输出”异常。这需要在main方法中用throws子句标记,如下所示:
public static void main(String[] args) throws IOException
{
Scanner in = new Scanner(Paths.get("myfile.txt"), "UTF-8");
...
}
程序的基本流程分为:顺序,分支和循环三种结构。
if(条件){
statement1;
}
else{
statement2;
}
分支语句–switch
使用switch时我们要注意:
变量类型是整数、字符、字符串(String)
case后面是常量
注意break
switch(exp){
case const1:
statement1;
break;
case const2:
statement2;
break;
...
case constN:
statementN;
break;
default:
statement_default;
break;
}
循环语句
循环语句主要有以下三种:
while语句。
do while语句。
for语句。
Goto语句
因为Goto语句在使用是会存在弊端,所以在Java中我们可以用break标号和continue标号来解决问题。其中,在循环前面用标号可以表明是那层循环。我们以以下程序为例:
label1:{....
label2: {....
label3: {....
break label2;
}
}
}
int []a;
double []b;
注意方括号可以写在变量前面,也可以写在变量后面。
int []a = new int[3];
a[0]=1;
a[1]=2;
a[2]=3;
int []a = {1,2,3};
int []a = new int[]{1,2,3};
我们不能像C/C++那样在java中初始化数组,原因在于 数组是引用(reference)类型。
int []a = new int[3]; //Here a is a reference
数组一经分配空间,其中的 每个元素 也被按照成员变量同样的方式被 隐式初始化。其中数值类型是 0 ,引用类型是 null。例如:
int []a = new int[5]; //Here a [3] is 0
我们可以使用a.length获取数组长度。
我们也可以使用Enhanced for语句来处理数组:
int []ages = new int[10];
for(int age: ages){
System.out.println(age);
}
这种语句为 只读式遍历
我们也可以使用System.arraycopy语句来复制数组:
//source array
int []source = {1,2,3,4,5,6};
//target array
int []dest = {10,9,8,7,6,5,4,3,2,1};
System.array(source,0,dest,0,source.length)
完成后dest为{1,2,3,4,5,6,4,3,2,1}
数组复制的常用方法有4种
for循环,效率最低
System.arraycopy() 效率最高
Arrays.copyOf() 效率次于第二种方法
Object.clone() 效率次于第二种和第三种
int [][]a={{1,2,3},{4,5,6},{7,8,9}};
我们要把Java中的数组同C/C++区分开来,我们以以下程序为例:
int [][]a=new int [3][];
a[0]=new int[2];
a[1]=new int[4];
a[2]=new int[3];