《Java核心技术卷一》 第3章 Java基本的程序设计结构

3.1 简单的Java程序

  1. Java语言中,对大小写敏感。

3.2 注释

Java中的注释不会出现在可执行程序中。在Java中,有三种注释方式:

  1. 最常用的方式是// ,从//开始到本行结束
  2. /* */ 将一段比较长的注释括起来。
  3. /** */ 这种注释用来自动生成文档。

3.3 数据类型

Java是一种强类型语言。 在Java中,一共有8种基本类型(primitive type),其中包含4种整型(byte, short , int , long),2种浮点型(float , double) , 1种字符类型(char) , 1种布尔类型(boolean)。

3.3.1 整型

类型存储需求取值范围
int4字节-2147483648~2147483647(正好超过20亿)
short2字节-32768~32767
long8字节-9223372036854775808~9223372036854775807
byte1字节-128~127

注意,Java没有任何无符号类型。

3.3.2 浮点型

类型存储需求取值范围
float4字节大约±3.40282347E+38F(有效位6~7位)
double8字节大约±1.79769313486231570E+308(有效位15位)

double表示类型是float类型的两倍(所以有人又称double为双精度类型),绝大多数时候都用double。float数值后有后缀F(如3.402F),没有F默认为double类型。

3.3.3 char

char类型用来表示单个字符。

3.3.4 布尔值

boolean类型有两个值:false和true,用来逻辑判断。整型值和布尔值之间不能进行相互转换。

3.4 变量

变量名必须是一个以字母开头的由字母、数字和_组成的序列。例如

int name ;

3.4.1 变量初始化

int age = 23 ;

在Java种,变量的声明尽可能地靠近第一次使用的地方,这是一种良好的程序编写风格。

3.4.2 常量

在Java中,利用关键字final声明常量。关键字final表示该变量只能被赋值一次,一旦被赋值,则不能进行修改。习惯上,常量名使用大写。
在Java中,通常希望一个常量能在一个类的多个方法中调用,通常称这些常量为类常量,可以使用staic final定义一个类常量。

    public static final double CM_PER_INCH = 2.54 ;

    public static void main(String[] args) {
        System.out.println(CM_PER_INCH);
    }

const是Java的保留字,但是目前并没有使用。在Java中,必须使用final定义常量

3.5 运算符

整数被0除将会产生一个异常,浮点数被0除将会得到无穷大或NaN结果。
可以在赋值语句中采用一种简化的格式书写二元运算符:

 x += 1 ;

等价于

x = x + 1 ; 

3.5.1 自增运算符与自减运算符

自增运算可以编写为

 int x = 1 ;
 x ++ ;  //x=2 ;

因为这些运算符改变的是变量的值,所以他的操作数不能是数值,即写作

13 ++ ;  

是一条非法语句。
实际上,自增有两种形式,即“前缀型”和“后缀型”。前缀型先自增在进行运算;后缀则相反。例如:

 int x = 1 ;
 int n = 2* ++x ; //前缀型,x先自增为2,n为4
 int n = 2* x++ ; //后缀型,先计算2*x=2,然后x自增为2,n为2

3.5.2 关系运算符与boolean运算符

关系运算符包括:!(非)、==(等于)、<(小于)、<=(小于等于)、>(大于)、>=(大于等于)、&&(逻辑与)、||(逻辑或)。
&&和||按照“短路”的方式求值。如果第一个操作数已经能够确定表达式的值,则第二个操作数就不必计算。
Java中的三元运算符:
condition ? expression1 : expression2 ;
当条件condition为真,计算expression1表达式,否则计算expression2表达式。

3.5.3 位运算符

在处理整型数值时,可以直接对组成整型数值的各位进行操作。这意味着可以使用屏蔽技术获得整数中的各个位。位运算符包括:
&(与) 、|(或) 、 ^(异或) 、~(非)
若用二进制表示的n的从右往左第4位为1,那么

 int fourthBitFromRight = ( n & 8 ) / 8 ;

返回1,否则返回0。
此例通过运用2的幂次方的&运算屏蔽了其他位,而只保留其中的某一位。
&与|不是按照短路方式计算的。

和<<运算符将二进制位进行右移或左移。当需要建立位模式屏蔽某些位时,使用这两个运算符十分方便。上面的例子等价于

 //1左移3位几位8。右移3位相当于除以8
 int fourthBitFromRight = ( n & (1 << 3) ) >> 3 ; 

最后, >>>运算符将用0填补高位(即逻辑移位); >>运算符用符号位填充高位(即算术移位)。没有<<<运算符!

3.5.4 数学函数与常量

在Math类中,包含了各种各样的数学函数。

 	double x = 4 ; 
 	Math.sqrt(x) ; //平方根
	Math.pow(x , 2) ; //x的2次方
         //三角函数
        Math.sin(x) ;
        Math.cos(x) ;
        Math.tan(x) ;
        Math.atan(x) ;
        
        Math.exp(x) ; //指数函数
        Math.log(x) ; //对数函数
        
        //表示Π和e的常量
        Math.PI;
        Math.E ;

3.5.5 数值类型之间的转换

在程序运行时,经常需要将一种数值类型转换为另一种数值类型。
image.png

6个实心箭头表示无信息丢失;3个虚心箭头表示可能有精度损失的转换。
当使用两个不同类型的数值进行二元操作时(如n+f,n是int,f是float),先将两个操作数转换为同一类型,然后再进行计算。

  • 如果两个操作数有一个是double,另一个操作数转换为double
  • 否则,如果其中一个操作数是float,另一个操作数转换为float
  • 否则,如果其中一个操作数是long,另一个操作数是转换为long
  • 否则,两个操作数都转换为int

3.5.6 强制类型转换

在必要的时候,int会自动转换为double。但另一方面,也有double需要转换为int的时候。在Java中,允许进行这种数值间的类型转换。当然,有可能会丢失一些信息。在这种情况下,需要通过强制类型转换(cast)实现这个操作。

double x = 9.997
int nx = (int) x ;

这样,nx变量的值为9。强制类型转换通过截断小数部分将浮点值转换为整型
如果想对浮点数进行舍入运算,以便得到最接近的整数(在很多情况下,希望使用这种操作方式),那么就需要使用Math.round()方法

double x = 9.997 ;
int nx = (int)Math.round(x) ;

现在nx的值为10.当调用round的时候,仍然需要使用强制类型转换(int)。其原因是round方法返回的结果为long类型。

不要在boolean类型与任何数值类型之间进行强制类型转换

3.5.7 括号与运算符级别

下图给出运算符级别。同一个级别的运算符按照从左到右的次序计算(除了表中给出的右结合运算符外)。
例如
因为+=是右结合运算符,所以表达式

a += b += c ;

等价于

 a += (b += c)

image.png
image.png

3.5.8 枚举类型

从JDK5.0开始,可以自定义枚举类型。枚举类型包括有限个命名的值。
例如

enum Size {
   SMALL ,
   MEDIUM ,
   LARGE ,
   EXTRA_LARGE
};

现在,可以生命这样一种类型变量:

Size s = Size.MEDIUM ;

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

3.6 字符串

Java没有内置的字符串类型,而是在标准的Java类库中提供了一个预定义类String。每个用双引号括起来的字符串都是String类型的一个实例。

String e = "" ;  //空字符串
String greeting = "Hello" ;

3.6.1 子串

String类型的**substring()**可以从一个较大的字符串提取一个子串。

        String greeting = "Hello" ;
        String s = greeting.substring(0,3) ; //区间左闭右开
	//s= "Hel"

substring()的工作方式有一个优点:容易计算子串的长度。字符串s.substring(a,b)的长度为b-a。

3.6.2 拼接

与绝大多数程序设计语言一样,Java语言允许使用+拼接两个字符串。

        String greeting = "Hello" ;
        //String s = greeting.substring(0,3) ;
        String s = "World!" ;
        System.out.println(greeting+s);
	//输出 HelloWorld!

当将一个字符串与一个非字符串的值进行拼接时,后者被转换成字符串

3.6.3 不可变字符串

String类没有提供用于修改字符串的方法。由于不能修改字符串中的字符,所以在Java文档中将String类对象称为不可变字符串。
不可变字符串有一个优点:编译器可以让字符串共享。

为了弄清具体的工作方式,可以想象将各种字符串存放在公共的存储池中。字符串变量指向存储池中的对应位置。如果复制一个字符串变量,原始字符串与复制的字符串指向存储池中的相同位置,共享相同的字符

3.6.4 检测字符串是否相等

可以使用equals方法检测两个字符串是否相等。

s.equals(t) ;

想要检测两个字符串是否相等,但不区分大小写,可以使用equalsIgnoreCase()。

System.out.println("HELLO".equalsIgnoreCase("hello"));
//返回TRUE

一定不能使用运算符检测两个字符串是否相等! 这个运算符只能够确定两个字符串是否放置在同一个位置上。
如果虚拟机始终将相同的字符串共享,就可以使用检测是否相等。但实际上只有字符串常量是共享的,而+或substring等操作产生的结果并不是共享的。

== 与 equals的却别

  1. 对于==,如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;

    如果作用于引用类型的变量,则比较的是所指向的对象的地址

  1. 对于equals方法,注意:equals方法不能作用于基本数据类型的变量

    如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;

    诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容。

3.6.6 字符串API

汇总常用的一部分String方法

    //按照字典顺序,如果字符串位于other之前,返回负数,在other之后,返回正数,相等返回0
    int compareTo(String other)
    
    //如果字符串以suffix结尾,返回true
    boolean endsWith(String suffix)
     
    //如果字符串与other相等,返回true
    boolean equals(Object other)

    //如果字符串相等(忽略大小写),返回true
    boolean equalsIgnoreCase(String other)

    //返回与字符串str匹配的第一个子串的开始位置,这个位置从0或者fromIndex开始计算。如果找不到,返回-1
    int indexOf(String str)
    int indexOf(String str , int fromIndex)

    //返回与字符串str匹配的最后一个子串的开始位置,这个位置从原始串的尾端或fromIndex开始计算。
    int lastIndexOf(String str)
    int lastIndexOf(String str , int fromIndex)

    //返回字符串的长度
    int length() 
   
    //返回一个新字符串。这个字符串用newString代替原始字符串中所有oldString
    String replace(String oldString , String newString)

    //如果字符串以preffix开始,返回true
    boolean startsWith(String preffix)

    //返回一个新字符串。这个字符串包含原始字符串[beginIndex,endIndex)的所有字符
    String substring( int beginIndex )
    String substring( int beginIndex , int endIndex )

    //返回一个新字符串。这个字符串将原始字符串中所有大写字母改成小写
    String toLowerCase() 

    //返回一个新字符串。这个字符串将原始字符串中所有小写字母改成大写
    String toUpperCase()

    //返回一个新字符串。这个字符串删除了原始字符串头部和尾部的空格
    String trim() 

3.6.8 构建字符串

有些时候,需要由较短的字符串构建字符串。若每次都拼接字符串,都会构建一个新的String对象,既耗时又浪费空间。使用StringBuilder类可以避免这个问题。

        StringBuilder builder = new StringBuilder();
        //当需要添加一部分内容时,调用append()方法
        builder.append("Hello");
        builder.append("World");
        //使用toString()方法,可以得到一个String对象
        String str = builder.toString() ;
        System.out.println(str);
        //输出 HelloWorld

在JDK5.0中引入StringBuilder类。这个类的前身是StringBuffer,其效率略微有些低,但允许使用多线程的方式执行添加或删除字符的操作。如果所有字符串在一个单线程中(通常都是这样)编辑,则应该使用StringBuilder替代它。这两个类的API是相同的。

下面是StringBuilder类中的重要方法

    //构造一个空的字符串构建器
    StringBuilder()

    //返回构建器或缓冲器中的字符数量
    int length() 

    //追加一个字符串兵返回this
    StringBuilder append(String str)

    //将第i个字符改为为c
    void setCharAt(int i , Char c)

    //在offset位置插入一个字符串并返回this
    StringBuilder insert(int offset , String str)

    //删除[startIndex , endIndex)的字符
    StringBuilder delete( int startIndex , int endIndex )

    //返回一个与构建器或缓冲器内容相同的字符串
    String toString()

3.7 输入与输出

3.7.1 读取输入

要想通过控制台进行输入,首先需要构造一个Scanner对象,并于“标准输入流”System.in关联

        Scanner in = new Scanner(System.in) ;
        
        //输入一行字符串(以回车结束)
        String line = in.nextLine() ;
        //输入一个单词(以空格结束)
        String name = in.next() ;
        //输入一个整数
        int age = in.nextInt() ;
        //输入一个浮点数
        double price = in.nextDouble() ;

3.8 控制流程

3.8.1 条件语句

        if(  ){
            
        }
        else if(  ){
            
        }
        else{
            
        }

3.8.2 循环

        while( ){
            
        }

或者

        do{
            
        }while(  )  ;

3.8.4 确定循环

for循环语句是支持迭代的一种通用结构

for( int i = 0 ; i < 10 ; i++ ){
  	//TODO
}

3.8.6 终端控制流程语句

Java提供了一种带标签的break语句,用于跳出多种嵌套的循环语句。标签必须放在希望跳出的最外层循环之前,并且紧跟一个冒号。

        read_data:
        while( true ){
            for( int i = 0 ; i < 10 ; i++ ){
                break read_data;
            }
        }

注意:break只能跳出语句块,而不能跳入语句块。

continue语句将控制转移到最内层循环的首部。

3.9 大数值

如果基本的整数和浮点数精度不能够满足需求,那么可以使用java.math包中的两个很有用的类:BigInteger和BigDecimal。这两个类可以处理包含任意长度数字序列的值。BigInteger类实现了任意精度的整数运算,BigDecimal实现了任意精度的浮点数运算。
使用静态的valueOf方法可以将普通的数值转换为大数值:

BigInteger a = BigInteger.valueOf(100) ;

遗憾的是,大数值类型不能使用人们熟悉的算术运算符(+和*等)。而需要使用大数值类的add和multiply方法

        BigInteger a = BigInteger.valueOf(100) ;
        BigInteger c = BigInteger.valueOf(100) ;
        BigInteger b = a.add(c) ;  // b = a+c

BigInteger常用API

//返回这个大整数与other的和、差、积、商以及余数
BigInteger add(BigInteger ohter)
BigInteger subtract(BigInteger other)
BigInteger multiply(BigInteger other)
BigInteger divide(BigInteger other)
BigInteger mod( BigInteger other )

//大整数比ohter大,返回正数,比other小返回负数,相等返回0
int compareTo(BigInteger other)

//返回值等于x的大整数
static BigInteger valueOf(long x)

3.10 数组

数组是一种数据结构,用来存储同一类型值的集合
在声明数组变量时,需要指出数组类型(数据元素类型紧跟[])和数组变量名字。

int[] a ;

这条语句只是声明了变量a,并没有将a实例化。

int[] a = new int[100] ;

一旦创建了数组,就不能再改变它的大小。

3.10.1 For each循环

Java SE 5.0增加了一种功能很强的循环结构,可以依次处理数组中的每个元素而不必为指定下标值而分心。
格式为

for( variable : collection ){
    //TODO
}

定义一个变量variable暂存集合中的每一个元素,并执行相应语句。collection这一集合表达式必须是一个数组或者是一个实现了Iterator接口的类对象。
例如

        int[] a = { 1 ,2,3 } ;
        for (int element : a) {
            System.out.println(element);
        }

3.10.2 数组初始化以及匿名数组

在Java中,提供一种创建数组对象并同时赋予初始值的简化书写方式。

	int[] a = { 1 ,2,3 } ;

请注意,在这种语句中不需要调用new
匿名数组

new int[]{1,2,3} ;

3.10.3 数组拷贝

在Java中,允许将一个数组变量拷贝给另一个数组变量。这时, 两个变量将引用同一个数组

        int[] a  = {1,2,3,4,5} ;
        int[] b = a ;
        b[0] = 6 ;
        for (int element : a) {
            System.out.println(element);
        }
      //输出结果为 6,2,3,4,5   即修改b,a也会改变

如果希望将一个数组的所有制拷贝到一个新的数组中去,就要使用Arrays类的copyOf方法:

int[] b = Arrays.copyOf(a , a.length) ;
//第2个参数是新数组b的长度,这个方法通常同来增加数组的大小

3.10.5 数组排序

要想对数组排序,可以使用Arrays类中的sort方法

int[] a = new int[100]
...
Arrays.sort(a) ;

这个方法使用了优化的快速排序。

数组常用API

//返回a中数据元素的字符串,这些数据元素被放在一个中括号内,并用逗号分隔
 static String toString( type[] a )

//返回与a类型相同的数组,其长度为length或者end-start,数组元素为a的值
static type copyOf( type[] a , int length )
static type copyOf( type[] a , int start , int end )

//采用优化的快速排序对数组进行排序
static void sort( type[] a )

//采用二分搜索算法查找v。如果成功返回其下标,否则返回一个负数r。-r-1是为了保持a有序v应插入的位置
static int binarySearch( type[] a , type v )
static int binarySearch( type[] a , int start , int end , type v )

//将数组的所有数据元素值设置为v
static void fill( type[] a , type v )

//如果两个数组大小相同,并且下标相同的元素都对应相等,则返回true
static boolean equals( type[] a , type b )

3.10.6 多维数组

在Java中声明一个二维数组相当简单

double[][] balances ;

要想快速打印一个二维数组,可以调用

Arrays.deepToString(a);

3.10.7 不规则数组

不规则数组即每一行有不同的长度。要想创建一个不规则的数组,首先需要分配一个具有所含行数的数组

int[][] odds = new int[3][] ;

接下来分配这些行

for( int n = 0 ; n < 3 ; n++ ){
     odds[n] = new int[n+1] ; 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值