Java自学笔记(一)Java的基本程序设计结构

1. Java的基本程序设计结构

1.1 一个简单的Java程序

public class FirstSample {
    public static void main(String[] args)
    {
        System.out.println("Hello  World");
    }
}

对于上述代码,我们需要注意以下几点:

  1. public为访问修饰符,class后面跟的是类名,关于类名的命名方法,推荐 驼峰命名法,例如FirstSample、CamelCase

  2. 类名的首字母一般是大写。

  3. 源代码的文件名必须与公共类相同,且用.java作为拓展名,Java编译器会将上述字节码文件自动地命名为FirstSample.java

  4. 当使用
    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)

1.2 注释

注释主要分为以下三种

  1. // 用于单行注释

    扫描二维码关注公众号,回复: 11347192 查看本文章
  2. /* */用于长篇注释

  3. /**
    */这种用于自动生成文档

注意:Java代码中的 /* */ 注释不能嵌套,不能用这对符号直接将代码括起来当作注释,因为代码中可能包含 */

1.3 数据类型

  1. 数据类型决定数据的存储方式和运算方式
  2. Java中的数据类型分为两大类:
    • 基本数据类型(primitive types)
    • 引用类型(reference types)
数据类型
基本数据类型
引用数据类型
数值型
整数类型:byte/short/int/long
浮点类型:float/double
字符型char
布尔型boolean
类Class
接口interface
数组

基本数据类型和引用数据类型的区别主要在于:

  1. 基本类型变量在栈,引用类型变量引用在堆。

  2. 赋值时,基本数据类型复制的是值,引用数据变量复制的是引用。

1.3.1 整型

四种数据类型:

类型 占用存储空间 表示范围
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,我们需要注意以下几点

  1. 长整型后有一个后缀Ll(例如4000000000L).十六进制有0X或0x做前缀。八进制有一个0作为前缀(例如010表示8),但容易混淆

  2. 可以使用0b或者0B写二进制数,也可以为数字位加下划线100_000_000

  3. Java没有无符号(unsigned)的整型,可以用long来处理。

1.3.2 浮点类型

java提供了两种浮点型变量,包括float double,我们需要注意以下几点

  1. float类型的数值后面有一个Ff作为后缀,没有后缀的默认为double类型

  2. double类型的数值后面有一个Dd作为后缀

浮点数计算的出错表示为以下三个特殊的浮点值

  1. 正无穷大

  2. 负无穷大

  3. NaN(不是一个数字)

这三个特殊的值分别表示为Double.POSITIVE_INFINITYDouble.NEGATIVE_INFINITYDouble.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)

1.3.3 char类型

Java字符采用Unicode编码,每个字符占用两个字节。

特殊字符的转义序列

转义序列 名称 Unicode值
\b 推格 \u0008
\t 制表 \u0009
\n 换行 \u000a
\r 回车 \u000d
\“ 双引号 \u0022
单引号 \u0027
\ 反斜杠 \u005c

Unicode转义序列会在解析代码之前进行处理,故可能发生以下错误:

  1. “\u0022+\u0022"会变为”"+""

  2. 要注意注释中的\u,例如:

    // \u00A0 is a newline
    

    会产生一个错误,因为\u00A0会替换为一个换行符

  3. 类似的

    // Look inside C:\users
    

    会产生一个错误,因为\u后面不是十六进制数

1.3.4 Unicode和char类型

1.3.5 boolean类型

  • boolean类型适用于逻辑运算,一般用于程序流程控制。
  • boolean类型数据主要取true和false值。
  • 在这里主要强调整数型与布尔值之间不能相互转换

1.4 变量(type)

提示:如果想知道那些Unicode字符属于Java中的“字母”,可以使用Character类的以下两种方法

Character.isJavaIdentifierStart(char ch/int codePoint)
Character.isJavaIdentifierPart(char ch/int codePoint)

1.4.1 变量初始化

相关语法可以类比C\C++,在这里主要强调java不区分声明与定义,例如:

int a = 10; //这是一个定义

extern int i; //这是一条声名

1.4.2 常量

在java中用final表示常量

public class FirstSample{
    public static void main(String[] args){
        final int A = 10;
    }
}

final表示这个常量只能被赋值一次,习惯上常量名使用全大写

1.5 运算符

相关语法可以类比C\C++

由于浮点数的计算存在精度问题,那么有strictfp关键字解决,如果将一个类标记为strictpf,那么这个类中的所有方法要使用严格的浮点计算

1.5.1 数学函数与常量

在Math类中,包含了各种各样的方法。例如以下程序:

double x=4;
double y=Math.sqrt(x);

在Math类中,提供了一些基本的函数:

  1. 三角函数类
Math.sin(10)
Math.cos(10)
Math.tan(10)
Math.atan(10)
Math.atan2(10)
  1. 指数函数及其反函数
Math.exp(10)
Math.log(10)
Math.log10(10)
  1. 最后,还提供了用于表示πe的近似值
Math.E
Math.Pi

floorMod方法的目的是解决整数余数的问题

1.5.2 数值类型的转换

下图表示数值类型之间的合法转换,实心箭头表示精度不会损失,虚线箭头表示会有精度损失

byte
short
int
long
double
float
char

在进行计算时,需要把操作数转换成同一种类型,然后再进行计算

  • 如果两个操作数中有一个是double类型,另一个操作数会被转换成double类型

  • 否则,如果两个操作数中有一个是float类型,另一个操作数会被转换成float类型

  • 否则,如果两个操作数中有一个是long类型,另一个操作数会被转换成long类型

  • 否则,两个操作数都会转换成int类型

1.5.3 强制类型转换

以下为示例程序:

int x = 10;
double y = (double) x;

但要注意,不要超过目标类型的范围

1.5.4 结合赋值和运算符

例如+=、-=等

1.5.5 自增与自减运算符

例如++、–等

1.5.6 关系与boolean运算符

例如==、!=、<=等

1.5.7 位运算符

位运算符主要有以下几种:
&,|,^,~,>>,<<,>>>

1.5.8 括号与运算符级别

不在此过多阐述,自行百度

1.5.9 枚举类型

有时候,变量的取值只在一个有限的集合内。例如:销售的服装或比萨饼只有小、中、大和超大这四种尺寸。当然,可以将这些尺寸分别编码为1、2、3、4或S、M、L、X。但这样存在着一定的隐患。在变量中很可能保存的是一个错误的值 (如0或m)。针对这种情况,可以自定义枚举类型。枚举类型包括有限个命名的值。例如:

enum Size { SMALL, MEDIUM, LARGE, EXTRA _LARGE };

现在,可以声明这种类型的变量:

Size S = Size.MEDIUM;

Size类型的变量只能存储这个类型声明中给定的某个枚举值,或者null值,null 表示这个变量没有设置任何值

1.6 字符串

从概念上讲,Java字符串就是Unicode字符序列。例如,串“Java\u2122"由5个Unicode字符J、a、v、a和T。Java没有内置的字符串类型,而是在标准Java类库中提供了一个预定义类,很自然地叫做String。每个用双引号括起来的字符串都是String类的个实例:

String e=""; // an empty string
String greeting = "Hello" ;

1.6.1子串

String类的 substring(a,b) 方法可以从一一个较大的字符串提取出一个子串。例如:

String greeting= "He11o";
String S = greeting. substring(0, 3);

创建了一个由字符“Hel” 组成的字符串。字符串长度为b-a

1.6.2 拼接

与绝大多数的程序设计语言一样,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"

1.6.3 不可变字符串

由于不能修改Java字符串中的字符,所以在Java文档中将Stirng类对象称为不可变字符串,不同于在C/C++中,字符串被认为是字符型数组,Java中字符串大致类似于char*指针。但是如果我们想将字符串“Hello!”转换为“Help!”,我们可以使用以下方法:

String str="hello!";
str=str.substring(0,3)+"p!";

1.6.4 检测字符串是否相等

可以使用equals方法检测两个字符串是否相等。对于表达式

s.eaquls(t);

如果字符串s与字符串t相等,则返回true;否则,返回false。需要注意,s与t可以是字符串变量,也可以是字符串字面变量,例如,下列表达式是合法的

"Hello".equals(greeting);

如果想要检测两个字符串大小是否是否相等,而不区分大小写,可以使用equalsIgnoreCase方法

"Hello".equalsIgnoreCase("HELLO");

注意:尽可能不要使用==判断两个字符串是否相等

1.6.5 空串与NULL串

空串“”是长度为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值上调用方法,会出现错误。

1.6.6码点与代码单元

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);

1.6.7 String API

1.6.8 阅读联机API文档

让浏览器指向安装JDK的docs/api/index.html子目录即可

1.6.9 构建字符串

有些时候,需要由较短的字符串构建字符串,例如,按键或来自文件中的单词。采用字符串连接的方式达到此目的的效率又比较低。每次连接字符串,都会构建一个新的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();

1.7 输入输出

1.7.1 文本界面

1.7.1.1 读取输入

1.7.1.1.1 使用Scanner

要想使用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方便。每次只能读取一-行输入,而没有能够读取一个单词或一个数值的方法。

1.7.1.1.2 使用in及out

在这里使用到了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);
    }
}

1.7.1.2 格式化输出

Java SE 5.0沿用了C语言库中的printf方法。 我们可以使用以下语句作为参考:

System.out.printf("You have entered: %s",a);

1.7.2 图形界面

我们以设计一个简单的平方计算器为例子:

1.7.2.1 使用JFrame

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);
    }
}

1.7.2.2 使用JApplet

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);
        });
    }
}

1.7.3 文件的输入与输出

要想对文件进行读取,就需要一个用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");
    ...
}

1.8 控制流程

程序的基本流程分为:顺序,分支和循环三种结构。

  • 分支语句–if
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;
                 }
            }
       }

1.9 大数组

1.10 数组

1.10.1 一维数组的声明方式:

int []a;
double []b;

注意方括号可以写在变量前面,也可以写在变量后面。

1.10.2 数组的初始化

int []a = new int[3];
a[0]=1;
a[1]=2;
a[2]=3;
int []a = {12,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获取数组长度。

1.10.3 Enhanced for

我们也可以使用Enhanced for语句来处理数组:

int []ages = new int[10];
for(int age: ages){
    System.out.println(age);
}

这种语句为 只读式遍历

1.10.4 复制数组

我们也可以使用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种

  1. for循环,效率最低

  2. System.arraycopy() 效率最高

  3. Arrays.copyOf() 效率次于第二种方法

  4. Object.clone() 效率次于第二种和第三种

1.10.5 多维数组

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];

参考资料

  1. Java核心技术 卷1 Cay S.Horstmann 著。
  2. MOOC 课堂 Java程序设计 唐大仕主讲,点击Java程序设计了解更多
  3. 菜鸟教程,点击菜鸟教程了解更多

猜你喜欢

转载自blog.csdn.net/weixin_43699716/article/details/104685777