java 基础编程

目录

java结构解析 

内置关键字 

注释

java 基本数据类型

java 类和对象

构造器

构造器初始化顺序 

super 关键词

new关键字

this 关键词 

instanceof 运算符

修饰词

字段

方法

字符串

String

StringBuilder类

包装类型

自动装箱和拆箱

枚举类型

表达式

文字

操作符

类型转换

控制语句

ForEach Loop

输出

System.out

System.out.format() 

java.util.Formatter 

 输入

java.util.Scanner

 软件开发

设计

Documentation and Style 

Javadoc


java结构解析 

内置关键字 

java内部保留词汇。这些名称不能用作类、方法或变量名称。

注释

java使用双引号“//”来进行一行的注释,利用“/*”开始注释块和“*/”表示结束。以“/**”开头和“*/”结束的块注释具有特殊用途,允许名为javadoc的程序读取这些注释并自动生成软件文档。

//This is an inline comment.
/*
* This is a block comment.
*/

java 基本数据类型

Base Types
boolean布尔值:true or false
char16位Unicode字符
byte8位有符号二进制整数
short16位有符号二进制整数
int 32位有符号二进制整数
long 64位有符号二进制整数
float32位浮点数
double64位浮点数

java 类和对象

构造器

构造函数是一种特殊的方法,用于初始化新创建的类实例,使其处于一致和稳定的初始状态。构造函数的定义方式与类的其他方法非常相似,但有一些重要区别:

  1. 构造函数不能是static、abstract或final,因此只允许那些影响可见性的修饰符(即public、protected、private或默认包级别的可见性)。
  2. 构造函数的名称必须与它构造的类的名称相同
  3. 我们没有为构造函数指定返回类型(甚至不是void)。构造函数的主体也不会显式返回任何内容。
modifiers name(type0 parameter0 , . . . , typen−1 parametern−1) {
    // constructor body . . .
}

构造器初始化顺序 

在类的内部,变量定义的先后顺序决定了初始化顺序。即使变量定义散布于方法定义之间,他们仍旧会在任何方法(包括构造器)被调用之前得到初始化。

class Window {
  Window(int marker) { print("Window(" + marker + ")"); }
}

class House {
  Window w1 = new Window(1); // Before constructor 第一
  House() { // Show that we're in the constructor: 第四
    print("House()");
    w3 = new Window(33); // w3在构造器内再次被初始化
  }
  Window w2 = new Window(2); // After constructor  第二
  void f() { print("f()"); }
  Window w3 = new Window(3); // At end             第三
}

public class OrderOfInitialization {
  public static void main(String[] args) {
    House h = new House();
    h.f(); // Shows that construction is done
  }
} /* Output:
Window(1)
Window(2)
Window(3)
House()
Window(33)
f()
*/

无论创建多少对象,静态数据都只占有一份存储区域。初始化顺序是先静态对象,而后非静态对象。 Java允许将多个静态初始化动作组织成一个“静态子句”(“静态块”)。与其他静态初始化动作一样,静态块代码仅执行一次:当首次生成这个类的一个对象时,或者首次访问属于那个类的静态成员时(即便从未生成过那个类的对象)。下面为对象创建过程:

  1. 查询.class文件的路径
  2. 载入.class文件,执行对象的静态方法或者静态属性域
  3. new对象,然后分配内存空间(内存空间清零,则对象回收,引用变成null)
  4. 执行属性域初始化
  5. 执行构造器

super 关键词

如果没有默认的基类构造器,或想用一个带参数的基类构造器,就必须使用super,显式地调用编写基类构造器的语句,并配以适当的参数列表: 

class Game {
  Game(int i) {
    print("Game constructor");
  }
}

class BoardGame extends Game {
  BoardGame(int i) {
    super(i);// 如果没有这一句,报错,找不到父类相关的构造器
    print("BoardGame constructor");
  }
}   
public class Chess extends BoardGame {
  Chess() {
    super(11);// 如果没有这一句,报错,找不到父类相关的构造器
    print("Chess constructor");
  }
  public static void main(String[] args) {
    Chess x = new Chess();
  }
} /* Output:
Game constructor
BoardGame constructor
Chess constructor
*///:~

new关键字

对象是能够承载数据类型值的载体。有三大重要特性:状态标识行为。对象的状态就是数据类型中的值。对象标识能够将一个对象区别于另一个对象,也是它在内存中的位置。对象行为就是数据类型的操作。每次调用new()系统都会:

  1. 为新的对象分配内存空间;所有实例变量都初始化为标准默认值。引用变量的默认值为空,基类型的默认值为0(布尔变量默认值为false
  2. 使用指定的参数调用新对象的构造函数(与类共享相同名称)初始化对象中的值;
  3. 返回该对象的一个引用(内存地址), 地址存储在对象变量中,因此,对象变量引用这个新创建的对象;

this 关键词 

在Java中的(非静态)方法的主体中,关键字this被自动定义为对调用该方法的实例的引用,指当前对象本身或当前类的一个实例,通过 this 可以调用本对象的所有方法和属性。

  • 将引用存储在变量中,或将其作为参数发送给另一个方法,该方法希望该类型的实例作为参数。
public class Demo{
    public int x = 10;
    public int y = 15;
    public void sum(){
        // 通过 this 点取成员变量,obj 是 Demo 类的一个实例,this 与 obj 等价
        int z = this.x + this.y;
        System.out.println("x + y = " + z);
    }
    public static void main(String[] args) {
        Demo obj = new Demo();
        obj.sum();
    }
}
  • 区分实例变量和同名的局部变量
public class Demo{
    public String name;
    public int age;  
    public Demo(String name, int age){    //形参的作用域是整个方法体,是局部变量。
        this.name = name;
        this.age = age;
    }   
}
  • 允许一个构造函数体调用另一个构造函数体。
public Counter( ) {
    this(0); // 调用一个值为零的参数构造函数
}

instanceof 运算符

该运算符用于操作对象实例,检查该对象是否是一个特定类型(类类型或接口类型)。如果运算符左侧变量所指的对象,是操作符右侧类或接口(class/interface)的一个对象,那么结果为真。

( Object reference variable ) instanceof  (class/interface type)

修饰词

包访问权限(默认)

默认访问权限没有任何关键词,意味着当前的包中的所有其他类对那个成员都有访问权,但对于包之外的所有类,这个成员是private。

Protected:继承访问权限

 被 protected 修饰的成员对于本包和其子类可见,Protect也提供包访问权限,也就是说,相同包内的其他类可以访问protected元素,protected的可见性在于两点: 

  • 基类的 protected 成员是包内可见的,并且对子类可见;
  • 若子类与基类不在同一包中,那么在子类中,子类实例可以访问其从基类继承而来的protected方法,而不能访问基类实例的protected方法。

static 修饰词

当声明一个事物是static,这就意味着这个域或方法不会跟这个类的任何实例关联在一起。方便在没有创建对象的情况下来进行调用(方法/变量), 即被static关键字修饰的方法或者变量不需要依赖于对象来进行访问,只要类被加载了,就可以通过类名去进行访问。

class Statictest{
    static int i=47;
}
// 即使创建两个对象,也只有一个i存储空间,两个对象共享
Statictest st1=new Statictest();
Statictest st2=new Statictest();

abstract 修饰词

 类和方法可以声明为抽象的,他们只有自己的名字,但没有具体实现。抽象是为了把相同的但不确定的东西的提取出来,为了以后的重用。

final 修饰词

如果类的成员变量声明为final,则通常也将其声明为static,只占据一段不能改变的存储空间,并且使用大写字母命名。一旦Final用于对象引用并被初始化指向一个对象,就无法把他指向另一个对象。对象自身是可以修改的:

private final Value v2 = new Value(22);//Value方法中有i变量
    fd1.v2.i++; // Object isn't constant!
     //! fd1.v2 = new Value(0); // Error: Can't

字段

声明类的一个或多个实例变量的一般语法如下(可选部分加括号):

[modifiers] type identifier1[=initialValue1], identifier2[=initialValue2];
  1. 始终尝试将所有字段声明为 private
  2. 创建一个将这些 private 字段当做输入的构造函数
  3. 创建一个设置每个 private 字段的 public 方法,这样你就知道何时更改了字段。这些方法叫做 setter
  4. 创建一个返回每个 private 字段的 public 方法,这样你就能够读取该字段,而不会不小心更改了它。这些方法叫做 getter

方法

如果方法没有返回值,returnType必须为void。Java方法只能返回一个值。为了在Java中返回多个值,我们应该把我们想要返回的所有值组合在一个复合对象中,它的实例变量包括所有要返回的值,然后返回对该复合对象的引用。 

[modifiers] returnType methodName(type1 param1 , . . . , typen paramn) {
      // method body . . .
}

private 方法通常称之为 helper 方法,因为它们只能被相同的类看到和调用,它们通常是为了帮助整理代码并使代码看起来更简单易读。public 方法是类可以执行的实际操作,基本上是程序的剩余部分能够看到和调用的方法。 以下是何时最好使用 public 方法与 private 方法的示例

class Person{
   private String userName;
   private String SSN;
   private String getId(){
      return SSN + "-" + userName;
   }
   public String getUserName(){
      return userName;
   }
   public boolean isSamePerson(Person p){
      if(p.getId().equals(this.getId()){
         return true;
      }
      else{
         return false;
      } 
   }
}

字符串

Java的char基类型存储一个表示单个文本字符的值。在Java中,所有可能的字符集是Unicode国际字符集,它是覆盖大多数常用书写语言的16位字符编码。

String类

String 的值是不可变的,每次对String的操作都会生成新的String对象,以包含修改后的字符串内容

索引 Indexing

字符串s中的每个字符c都可以通过使用索引引用,该索引等于s中c之前的字符数。根据此约定,第一个字符位于索引0,最后一个字符位于索引n-1,其中n是字符串的长度。

String内置方法
length()返回字符串长度
charAt(k)返回第k个索引的字符

在Java中,“+”操作在对两个字符串作用时执行串接

String term = "over" + "load";

StringBuilder类

Java的字符串类的一个重要特性不可变性(immutable),可以在Java虚拟机内实现高效和优化。但是字符串类型的变量可以重新分配给另一个字符串实例。

String greeting = "Hello";
greeting = "Ciao"; // we changed our mind
greeting = greeting + '!'; // now it is ”Ciao!”

每次使用 System.String类中的方法之一时,都要在内存中创建一个新的字符串对象,这就需要为该新对象分配新的空间。在需要对字符串执行重复修改的情况下,与创建新的 String对象相关的系统开销可能会非常昂贵。为了支持更有效的字符串编辑,Java提供StringBuilder类,它实际上是字符串的可变版本。

StringBuilder 内置方法
setCharAt(k,c):将索引k的字符改为c
insert(k, s):从序列的索引k开始插入字符串s的副本,将现有字符移动以腾出空间。
append(s)将字符串s附加到序列的末尾。
reverse()反转当前序列顺序。
toString():返回基于当前字符序列的传统字符串实例。

数组

存储在数组中的每个值都称为该数组的元素。我们将数组的长度称为它的容量。在Java中,可以使用a.length得到a的数组的长度。数组A的单元格编号为0、1、2直至a.length−1,并且索引为k的单元格通过a[k]访问。

声明和构造数组

  • 创建数组的第一种方法是在最初声明数组时使用对文本形式的赋值,使用如下语法:
elementType[ ] arrayName = {initialValue0, initialValue1, . . . , initialValueN−1};
int[ ] primes = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
  • 创建数组的第二种方法是使用new运算符。但是,由于数组不是类的实例,因此我们不使用典型的构造函数语法: 使用new运算符创建数组时,将自动为其所有元素指定元素类型的默认值。
new elementType[length]
double[ ] measurements = new double[1000];

数组复制

将变量备份分配给数据不会创建任何新的数组;它只是为同一个数组创建一个新的别名

int[ ] data = {2, 3, 5, 7, 11, 13, 17, 19};
int[ ] backup;
backup = data; // warning; not a copy

clone()方法生成数组的浅副本,生成一个新数组,该数组的单元格引用第一个数组引用的相同对象。 

backup = data.clone();

可以通过重复克隆单个元素来创建深度副本,如下所示,但前提是Person类声明为Cloneable. 

Person[ ] guests = new Person[contacts.length];
for (int k=0; k < contacts.length; k++)
    guests[k] = (Person) contacts[k].clone( ); // returns Object type

数组结构分析

我们研究的第一个应用是向数组中存储游戏的高分条目,条目是一个键值对包括名称和分数。

public class GameEntry {
    private String name;
    private int score;
    /** Constructs a game entry with given parameters */
    public GameEntry(String n,int s){
        name = n;
        score = s;
    }
    /**Returns the name field*/
    public String getName(){return name;}
    /** Returns the score field. */
    public int getScore() {return score;}
    /** Returns a string representation of this entry. */
    @Override
    public String toString() {
        return "(" + name +","+score+")";
    }
}

为了记录得到的分数,设计一个名为记分板的类。一个记分板只能保存一定数量的高分;一旦存储数量达到这一限制,一个新的分数只有在严格高于最低的“高分”时才符合记分板的资格。由于个数限制可能会有所不同,我们允许将它指定为记分板构造函数的参数。

/** Class for storing high scores in an array in nondecreasing order. */
public class Scoreboard {
    private int numEntries = 0;
    private GameEntry[] board;
    public Scoreboard(int capacity){
        board = new GameEntry[capacity];
    }
    // more methods will go here
}

添加条目

  public void add(GameEntry e){
        int newScore = e.getScore();
        if (numEntries < board.length || newScore > board[numEntries-1].getScore()){
            if (numEntries < board.length)
                numEntries++;
            // 向右移动任何较低的分数,为新条目腾出空间
            int j = numEntries-1;
            while (j>0 && board[j-1].getScore()<newScore){
                board[j] = board[j-1];
                j--;
            }
            board[j] = e;
        }
    }

 

删除条目

    /** Remove and return the high score at index i. */
    public GameEntry remove(int i) throws IndexOutOfBoundsException{
        if (i<0 || i>=numEntries)
            throw new IndexOutOfBoundsException("Invalid index: " + i);
        GameEntry temp = board[i];
        for (int j=i;j<numEntries-1;j++)
            board[j]= board[j+1];
        board[numEntries-1] = null;
        numEntries--;
        return temp;
    }

插入排序算法

Algorithm InsertionSort(A):
    Input: An array A of n comparable elements
    Output: The array A with elements rearranged in nondecreasing order
    for k from 1 to n−1 do
        Insert A[k] at its proper location within A[0], A[1], . . ., A[k].

 public static void insertionSort(char[] data){
        int n = data.length;
        for (int k=1;k<n;k++){
            char cur = data[k];
            int j=k;
            while (j>0 && data[j-1]>cur){
                data[j] = data[j-1];
                j--;
            }
            data[j] = cur;
        }
    }

java.util.Arrays

由于数组非常重要,Java提供了一个类java.util.Arrays,其中有许多内置的静态方法来执行数组上的常见任务。

java.util.Arrays 内置方法
equals(A, B)仅当数组A和数组B相等时返回true。如果两个数组的元素数目相同,并且两个数组中每个对应的元素对相等,则认为两个数组相等
fill(A, x)在数组A的每个单元格中存储值x,前提是定义了数组a的类型
copyOf(A, n)返回一个大小为n的数组,该数组的前k个元素从A复制,其中k=min{n,A.length}。如果n>A.length,则该数组剩余元素将被数据类型的默认值填充
copyOfRange(A, s, t)返回一个大小为t−s的数组,其中元素为从A[s]复制到A[t−1],其中s<t
toString(A)返回数组A的字符串表示形式,以[开头,以]结尾,显示的元素以字符串“,”分隔。元素a[i]的字符串表示形式使用String.valueOf(A[i])获得,或者调用A[i].toString( )
sort(A)根据数组元素的自然顺序对数组A排序,该顺序必须是可比较的。
binarySearch(A, x)在排序数组A中搜索值x,返回找到它的索引,或者在保持排序顺序的同时,返回可以插入它的索引。

数组等效性 

a == b

测试A和B是否是相同数组对象

int[] a = {1,2,3};
int[] b ={1,2,3};
int[] c = a;
a == b; //false
a == c; //true

a.equals(b)

与 a==b 相同

a.equals(b)  //false

a.equals(c) //true

Arrays.equals(a,b)

如果数组的长度相同,并所对应位置元素相等,则返回true

Arrays.equals(a,b); //true
Arrays.equals(a,c); //true

Arrays.deepEquals(a,b)

支持多维数组的比较,Arrays.deepEquals(a[k],b[k])

 

java.util.Random

伪随机数:看起来是随机的数字(但不一定是真正随机的,可以预测给定过去数字列表的序列中的下一个数字)。Java有一个内置类java.util.Random,它的实例是伪随机数生成器。实际上,一个伪随机数生成器是根据当前的数字生成下一个数字,其中a、b和n是适当选择的整数,而%是模运算符:

next = (a * cur + b)\% n;

由于伪随机生成器中的下一个数字是由前一个数字确定的,因此此类生成器始终需要一个启动位置,称为其seed。相同的种子生成的数字序列将始终相同。java.util.random类实例的种子可以在其构造函数中设置,也可以使用其setSeed( )方法设置。每次运行程序时获取不同序列的一个常见技巧,我们可以使用来自用户的定时输入,或者我们可以将种子设置为自1970年1月1日以来的当前时间(由方法System.currentTimeMillis提供)。

java.util.Random 内置函数
nextBoolean( )返回下一个伪随机布尔值
nextDouble( )返回下一个伪随机双精度值,介于0.0和1.0之间
nextInt( )返回下一个伪随机int值

nextInt(n)

返回从0到n(不包括n)范围内的下一个伪随机int值

setSeed(s)

将此伪随机数生成器的种子设置为 long s

import java.util.Arrays;
import java.util.Random;

/** Program showing some array uses. */
public class ArrayTest {
    public static void main(String[] args){
        int data[] = new int[10];
        Random rand = new Random();
        rand.setSeed(System.currentTimeMillis());
        for (int i=0;i<data.length;i++)
            data[i] = rand.nextInt(100);
        int[] orig= Arrays.copyOf(data, data.length);
        System.out.println("arrays equal before sort: "+Arrays.equals(data,orig));
        Arrays.sort(data);
        System.out.println("arrays equal after sort: " + Arrays.equals(data,orig));
        System.out.println("orig = " + Arrays.toString(orig));
        System.out.println("data = " + Arrays.toString(data));
    }
}

二维数组

Java中的数组是一维的,我们使用单个索引访问数组的每个单元格。我们可以将二维数组定义为一个数组,其中每个单元格都是另一个数组:

int[ ][ ] data = new int[8][10];

Tic-Tac-Toe

基本思想是用二维数组来维护棋盘。Board是一个三乘三矩阵,此数组中的单元格存储的值指示该单元格是否为空或存储X或O。0表示空单元格,1表示x,−1表示o。如果行、列或对角线的值分别加起来为3或−3则胜利。


/** Simulation of a Tic-Tac-Toe game (does not do strategy). */
public class TicTacToe {
    public static final int X=1,O=-1;
    public static final int EMPTY=0;
    private int board[][] = new int[3][3];
    private int player;
    public TicTacToe(){clearBoard();}
    public void clearBoard(){
        for (int i=0;i<3;i++)
            for (int j=0;j<3;j++)
                board[i][j] = EMPTY;
        player = X;
    }
    /** Puts an X or O mark at position i,j. */
    public void putMark(int i,int j) throws IllegalArgumentException{
        if ((i < 0) || (i > 2) || (j < 0) || (j > 2))
            throw new IllegalArgumentException("Invalid board positiin");
        if (board[i][j] != EMPTY)
            throw new IllegalArgumentException("Board position occupied");
        board[i][j] = player;
        player = - player;
    }
    /** Checks whether the board configuration is a win for the given player. */
    public boolean isWin(int mark){
        return ((board[0][0] + board[0][1] + board[0][2] == mark*3) // row 0
        || (board[1][0] + board[1][1] + board[1][2] == mark*3) // row 1
        || (board[2][0] + board[2][1] + board[2][2] == mark*3) // row 2
        || (board[0][0] + board[1][0] + board[2][0] == mark*3) // column 0
        || (board[0][1] + board[1][1] + board[2][1] == mark*3) // column 1
        || (board[0][2] + board[1][2] + board[2][2] == mark*3) // column 2
        || (board[0][0] + board[1][1] + board[2][2] == mark*3) // diagonal
        || (board[2][0] + board[1][1] + board[0][2] == mark*3)); // rev diag
    }
    /** Returns the winning player's code, or 0 to indicate a tie (or unfinished game).*/
    public int winner(){
        if (isWin(X))
            return X;
        else if (isWin(O))
            return O;
        else
            return 0;
    }
    /** Returns a simple character string showing the current board. */
    public String toString(){
        StringBuilder sb = new StringBuilder();
        for (int i=0;i<3;i++){
            for (int j=0;j<3;j++){
                switch (board[i][j]){
                    case X: sb.append("X");break;
                    case O: sb.append("O");break;
                    case EMPTY: sb.append(" ");break;
                }
                if (j<2) sb.append("|");
            }
            if (i<2) sb.append("\n-----\n");
        }
        return sb.toString();
    }
    /** Test run of a simple game */
    public static void main(String[ ] args) {
        TicTacToe game = new TicTacToe();
        /* X moves: */ /* O moves: */
        game.putMark(1,1); game.putMark(0,2);
        game.putMark(2,2); game.putMark(0,0);
        game.putMark(0,1); game.putMark(2,1);
        game.putMark(1,2); game.putMark(1,0);
        game.putMark(2,0);
        System.out.println(game);
        int winningPlayer = game.winner();
        String[] outcome = {"O wins", "Tie", "X wins"};
        System.out.println(outcome[1 + winningPlayer]);
    }
}

包装类型

Java的库中有许多数据结构和算法,它们是专门设计的,以便只与对象类型配合工作。为了绕过这个障碍,Java为每个基类型定义了一个包装类。

Java 包装类
基本数据类型包装类名创建示例访问实例
booleanBooleanobj = new Boolean(true)obj.booleanValue()
charCharacterobj = new Charater('Z')obj.charValue()
byteByteobj = new Byte((byte) 34)obj.byteValue()
shortShortobj = new Short((short) 100)obj.shortValue()
intIntegerobj = new Integer(1045)obj.intValue()
longLongobj = new Long(10849L)obj.longValue()
floatFloatobj = new Float(3.934F)obj.floatValue()
doubleDoubleobj = new Double(3.934)obj.doubleValue()

自动装箱和拆箱

创建int类型值k,Java自动将int封箱,并隐式调用Integer(k)。反过来,对于任意已存在整数值v,Java将自动隐式调用v.intValue( )。其他基本类型的包装纸也进行了类似的转换。并且,所有包装器类型都支持在字符串文本之间来回转换。

int j = 8;
Integer a = new Integer(12);
int k = a; // 隐式调用a.intValue()
int m = j + a; // a在添加前自动解箱
a = 3 * m; // 结果在分配前自动装箱
Integer b = new Integer("-135"); //构造函数接受字符串
int n = Integer.parseInt("2013"); // 使用整数类的静态方法

枚举类型

Java通过定义枚举类型支持从有限集合中选择的更优雅的方法,而不是使用static final每个都声明一下:

modifier enum name { valueName0 , valueName1 , . . . , valueNamen−1 };
public enum Day { MON, TUE, WED, THU, FRI, SAT, SUN };

创建enum时,编译器会为您生成关联的类。 这个类自动从java.lang.Enum继承。一旦定义好day就成为正式数据类型,我们可以用day类型声明变量或参数,并对其进行赋值:

Day today;
today = Day.TUE;

通过调用enum中的values()来遍历enum常量列表。 values()方法按照它们被声明的顺序生成枚举常量的数组,因此可以在foreach循环中使用返回数组。 

 for(enumtype e : enumtype.values())

表达式

文字

文字是可以在赋值或其他表达式中使用的任何“常量”值。Java允许以下类型的文字:

  • null 对象引用
  • 布尔值:true和false
  • integer:像176或-52这样的整数的默认值是int类型。长整型文字必须以“L”或“l”结尾,例如176l或-52l。
  • Floating Point::浮点数(如3.1415和135.23)的默认值是双精度。要指定一个文本是一个Floating,它必须以“F”或“f”结尾。还允许使用指数符号表示的浮点文字,如3.14e2或.19e10;假定基数为10。
  • Character:在Java中,字符常量假设取自Unicode字母表。通常,字符定义为单引号中包含的单个符号。例如,“a”和“?'是字符常量。此外,Java定义了以下特殊字符常量:'\n' (newline) '\t' (tab) '\b' (backspace) '\r' (return) '\f' (form feed) '\\' (backslash) '\'' (single quote) '\"' (double quote).
  • 字符串文字:字符串文字是用双引号括起来的字符序列

操作符

布尔值操作符
not (prefix)
&&conditional and
||conditional or
位运算符
~位补码
&按位与
|按位或
^按位异或
<<向左移位,用零填充
>>向右移位,用符号位填充
>>>向右移位,用零填充

类型转换

强制转换是一种允许我们更改值类型的操作。本质上,我们可以取一个类型的值并将其转换为另一个类型的等效值。Java中有两种形式的强制转换:显式和隐式。

显式转换

(type) exp

double d1 = 3.2;
double d2 = 3.9999;
int i1 = (int) d1; // i1 gets value 3
int i2 = (int) d2; // i2 gets value 3
double d3 = (double) i2; // d3 gets value 3.0

String s1 = "2014";
int i1 = Integer.parseInt(s1); // i1 gets value 2014
int i2 = −35;
String s2 = Integer.toString(i2); // s2 gets value ”-35”

 隐式转换

有些情况下,Java将根据表达式的上下文执行隐式转换。例在执行扩大转换,而无需显式使用转换运算符。但执行收缩强制转换,则会导致编译器错误。

int i1 = 42;
double d1 = i1; // d1 gets value 42.0
i1 = d1; // 编译错误:可能的精度损失

//要执行到字符串的转换,必须使用适当的ToString方法或通过串联操作执行隐式转换
String s = Integer.toString(22); // this is good
String t = "" + 4.5; // correct, but poor style
String u = "Value = " + 13; // this is good

控制语句

if (firstBooleanExpression)
    firstBody;
else if (secondBooleanExpression)
    secondBody;
else
    thirdBody;
switch (d) {
    case MON:
        System.out.println("This is tough.");
        break;
    case TUE:
        System.out.println("This is getting better.");
        break;
    case WED:
        System.out.println("Half way there.");
        break;
    case THU:
        System.out.println("I can see the light.");
        break;
    case FRI:
        System.out.println("Now we are talking.");
        break;
    default:
        System.out.println("Day off!");
}
for (initialization; booleanCondition; increment)
    loopBody

ForEach Loop

用于数组和容器,表示不必创建int变量去对序列进行计数,foreach将自动产生每一项。任何返回一个数组的方法都可以使用foreach。 String类有一个方法toCharArray(),它返回一个char数组,因此可以很容易的将下面这样迭代在字符串里面的所有字符:

for (elementType name : container)
    loopBody

for(char c : "An African Swallow".toCharArray() )
    System.out.print(c + " ");

其中container是给定元素类型的数组。值得强调的是,对循环变量进行赋值对底层数组没有影响

public static void scaleBad(double[ ] data, double factor) {
    for (double val : data)
        val *= factor; // changes local variable only
}
public static void scaleGood(double[ ] data, double factor) {
    for (int j=0; j < data.length; j++)
        data[j] *= factor; // overwrites cell of the array
}

输出

System.out

Java提供了一个内置的静态对象System.out,,它执行输出到“标准输出”设备。system.out对象是java.io.printstream类的实例。此类定义缓冲输出流的方法,这意味着字符被放在一个称为缓冲区的临时位置,当控制台窗口准备打印字符时,缓冲区将被清空。

System.out 输出方法
print(String s)打印字符串s
print(Object o)使用对象本身的ToString方法打印对象o
print(baseType b)打印基类型值b
println(String s)打印字符串s,后跟换行符
println(Object o)类似于print(Object o),后跟换行符
println(baseType b)类似于print(Object o),后跟换行符

System.out.format() 

Format方法模仿C语言的printf(),两者等价:

public class SimpleFormat {
  public static void main(String[] args) {
    int x = 5;
    double y = 5.332542;    // The old way:
    System.out.println("Row 1: [" + x + " " + y + "]");    // The new way:
    System.out.format("Row 1: [%d %f]\n", x, y);    // or
    System.out.printf("Row 1: [%d %f]\n", x, y);
  }
} /* Output:
Row 1: [5 5.332542]
Row 1: [5 5.332542]
Row 1: [5 5.332542]
*/

java.util.Formatter 

您可以将Formatter视为翻译器,将格式字符串和数据转换为所需的结果。当您创建一个Formatter对象时,需要向构造器传递一些信息,告诉他最终结果输出到哪(最常用PrintStreams,OutputStream,andFile.)

import java.util.Formatter;  
public class Test {  
    private Formatter formatter = new Formatter(System.out);// 这里需要定义输出的地方  
      public void print(int a, String b) {  
        formatter.format("%d%s", a, b);  
    }    
    public static void main(String[] args) {  
        int a = 1;  
        String b = "b";  
        new Test().print(a, b);  
    }  
} /* output:
1b*///:~

要在插入数据时控制间距和对齐,您需要更详细的格式修饰符:

%[argument_index$][flags][width][.precision]conversion

width控制一个域的最小尺寸。Formatter对象通过在必要时添加空格,来确保达到某个长度。precision指明最大尺寸:Formatter提供了对空格和对齐的强大控制能力,下面的程序应用格式修饰符来打印一个购物收据: 

import java.util.*;

public class Receipt {
    private double total = 0;
    private Formatter f = new Formatter(System.out);
    public void printTitle() {
        f.format("%-15s %5s %10s\n", "Item", "Qty", "Price");
        f.format("%-15s %5s %10s\n", "----", "---", "-----");
    }
    public void print(String name, int qty, double price) {
        f.format("%-15.15s %5d %10.2f\n", name, qty, price);
        total += price;
    }
    public void printTotal() {
        f.format("%-15s %5s %10.2f\n", "Tax", "", total*0.06);
        f.format("%-15s %5s %10s\n", "", "", "-----");
        f.format("%-15s %5s %10.2f\n", "Total", "",
                total * 1.06);
    }
    public static void main(String[] args) {
        Receipt receipt = new Receipt();
        receipt.printTitle();
        receipt.print("Jack's Magic Beans", 4, 4.25);
        receipt.print("Princess Peas", 3, 5.1);
        receipt.print("Three Bears Porridge", 1, 14.29);
        receipt.printTotal();
    }
}
/*
Item              Qty      Price
----              ---      -----
Jack's Magic Be     4       4.25
Princess Peas       3       5.10
Three Bears Por     1      14.29
Tax                         1.42
                           -----
Total                      25.06
*/

 输入

java.util.Scanner

import java.util.Scanner; // loads Scanner definition for our use

public class InputExample {
    public static void main(String[ ] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("Enter your age in years: ");
        double age = input.nextDouble( );
        System.out.print("Enter your maximum heart rate: ");
        double rate = input.nextDouble( );
        double fb = (rate − age) * 0.65;
        System.out.println("Your ideal fat-burning heart rate is " + fb);
    }
}

scanner类读取输入流并将其划分为tokens,tokens是由分隔符分隔的字符串。

Scanner 类方法
hasNext( )如果输入流中还有其他tokens,则返回true。
next( )返回输入流中的下一个tokens字符串;如果没有剩余的tokens,则生成错误。
hasNextType( )如果输入流中有另一个tokens,并且可以将其解释为相应的基本类型。则返回true
nextType( )返回输入流中的下一个tokens所对应于的基本类型;如果没有剩余的tokens或下一个tokens无法解释为基本类型,则生成错误。
hasNextLine( ):如果输入流有另一行文本,则返回true。
nextLine( ):将输入推进到当前行尾,并返回跳过的输入。
findInLine(String s)尝试在当前行中查找与模式s匹配的字符串。如果找到模式,则返回该模式。如果找不到模式,则扫描器返回空值且不前进。
Scanner input = new Scanner(System.in);
System.out.print("Please enter an integer: ");
while (!input.hasNextInt( )) {
    input.nextLine( );
    System.out.print("Invalid integer; please enter an integer: ");
    } 
int i = input.nextInt( );

 软件开发

传统的软件开发涉及几个阶段。三个主要步骤是:1.Design;2.Coding;3.Testing and Debugging

设计

Documentation and Style 

Javadoc

为了鼓励使用块注释和自动生成文档,Java编程环境附带了一个文档制作程序JavaDoc。每个javadoc注释都是一个以“/*”开头并以“*/”结尾的块注释,这两个注释之间的每一行都可以以一个星号“*”开头,而忽略该星号。我们使用的主要javadoc标记如下:

  • @author text:标识类的作者
  • @throws exceptionname description: 描述由此方法发出信号的错误条件
  • @param parametername description:描述此方法接受的参数
  • @return description:描述方法的返回类型及其值范围

/**
 * A simple model for a consumer credit card.
 * @author linlinle
 * @author Michael T. Goodrich
 * @author Roberto Tamassia
 */
public class CreditCard {
    private String customer;
    private String bank;
    private String account;
    private int limit;
    protected double balance;
    /**
     * Constructs a new credit card instance.
     * @param cust the name of the customer (e.g., ”John Bowman”)
     * @param bk the name of the bank (e.g., ”California Savings”)
     * @param acnt the account identifier (e.g., ”5391 0375 9387 5309”)
     * @param lim the credit limit (measured in dollars)
     * @param initialBal the initial balance (measured in dollars)
     */
    public CreditCard(String cust, String bk, String acnt, int lim, double initialBal){
        customer = cust;
        bank = bk;
        account = acnt;
        limit = lim;
        balance = initialBal;
    }

    /**
     *Charges the given price to the card, assuming sufficient credit limit.
     * @param price the amount to be charged
     * @return true if charge was accepted; false if charge was denied
     */
    public boolean charge(double price){
        if (price+balance>limit)
            return false;
        balance +=price;
        return true;
    }

    /**
     * Processes customer payment that reduces balance.
     * @param amount the amount of payment made
     */
    public void makePayment(double amount){
        balance -= amount;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值