码迷,mamicode.com
首页 > 编程语言 > 详细

java编程思想总结(二)

时间:2016-06-29 17:20:50      阅读:272      评论:0      收藏:0      [点我收藏+]

标签:

java编程思想总结(二)

java编程思想总结是一个持续更新的系列,是本人对自己多年工作中使用到java的一个经验性总结,也是温故而知新吧,因为很多基础的东西过了这么多年,平时工作中用不到也会遗忘掉,所以看看书,上上网,查查资料,也算是记录下自己的笔记吧,过一段时间之后再来看看也是蛮不错的,也希望能帮助到正在学习的人们,本系列将要总结一下几点:

  • 面向对象的编程思想
  • java的基本语法
  • 一些有趣的框架解析
  • 实战项目的整体思路
  • 代码的优化以及性能调优的几种方案
  • 整体项目的规划和视角
  • 其它遗漏的东西以及补充

java的基本语法

结合上一节,我们也从最基本的类开始,首先是经典的hello word案例:

package com.klsstt.helloword; 

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

这个案例输出了“Hello Word !”,其中,关键字class,用来创建类,public则是访问修饰符,代表这个类的访问权限,HelloWord则是这个类的名称,一般类的命名都是首字母大写的驼峰命名法。package是包的声明,表明当前类的包路径,static关键字代表该方法是静态方法,main则是方法名称,main方法是java程序默认生成的可执行的方法。

大小写敏感性

Java 是一种大小写敏感的语言,这就意味着 Hello 和 hello 在 Java 中代表不同的意思。
Java 关键字总是小写的
避免使用只有大小写不同的变量名。

类的命名

所有类的名称首字母必须大写。
始终确保在您的代码和Java文件名相匹配的类名。
如果类名称中包含几个单词,那么每个单词的首字母都要大写。
例如类 HelloWord

Java 标识符

标识符就是用于给 Java 程序中变量、类、方法等命名的符号。
使用标识符时,需要遵守几条规则:

  1. 标识符可以由字母、数字、下划线(_)、美元符($)组成,但不能包含 @、%、空格等其它特殊字符,不能以数字开头。如:123name

  2. 标识符不能是 Java 关键字和保留字( Java 预留的关键字,以后的升级版本中有可能作为关键字),但可以包含关键字和保留字。如:不可以使用 void 作为标识符,但是 Myvoid 可以。

  3. 标识符是严格区分大小写的。 一定要分清楚Hello 和 hello 是两个不同的标识符哦!
  4. 标识符的命名最好能反映出其作用,做到见名知意。

Java 修饰符

访问修饰符:default, public , protected, private
非访问修饰符:final, abstract, strictfp

Java 关键字列表

访问控制
private 私有的
protected 受保护的
public 公共的

类、方法和变量修饰符
abstract 声明抽象
class 类
extends 扩允,继承
final 终极,不可改变的
implements 实现
interface 接口
native 本地
new 创建
static 静态
strictfp 严格,精准
synchronized 线程,同步
transient 短暂
volatile 易失

程序控制语句
break 跳出循环
continue 继续
return 返回
do 运行
while 循环
if 如果
else 反之
for 循环
instanceof 实例
switch 开关
case 返回开关里的结果
default 默认

错误处理
try 捕获异常
catch 处理异常
finally 有没有异常都执行
throw 抛出一个异常对象
throws 声明一个异常可能被抛出
assert 断言

包相关
import 引入
package 包

基本类型
boolean 布尔型
byte 字节型
char 字符型
double 双精度,
float 浮点
int 整型
long 长整型
short 短整型
null 空
true 真
false 假
enum 枚举

变量引用
super 父类,超类
this 本类
void 无返回值

关键字(51)+保留字(const,goto)共53个

Java 变量和常量

在程序中存在大量的数据来代表程序的状态,其中有些数据在程序的运行过程中值会发生改变,有些数据在程序运行过程中值不能发生改变,这些数据在程序中分别被叫做变量和常量。
在实际的程序中,可以根据数据在程序运行中是否发生改变,来选择应该是使用变量代表还是常量代表。

变量
变量代表程序的状态。程序通过改变变量的值来改变整个程序的状态,或者说得更大一些,也就是实现程序的功能逻辑。
为了方便的引用变量的值,在程序中需要为变量设定一个名称,这就是变量名。
例如在2D游戏程序中,需要代表人物的位置,则需要2个变量,一个是x坐标,一个是y坐标,在程序运行过程中,这两个变量的值会发生改变。

由于Java语言是一种强类型的语言,所以变量在使用以前必须首先声明,在程序中声明变量的语法格式如下:
数据类型 变量名称;
例如:int x;
在该语法格式中,数据类型可以是Java语言中任意的类型,包括前面介绍到的基本数据类型以及后续将要介绍的复合数据类型。变量名称是该变量的标识符,需要符合标识符的命名规则,在实际使用中,该名称一般和变量的用途对应,这样便于程序的阅读。数据类型和变量名称之间使用空格进行间隔,空格的个数不限,但是至少需要1个。语句使用“;”作为结束。
也可以在声明变量的同时,设定该变量的值,语法格式如下:
数据类型 变量名称 = 值;
例如:int x = 10;
在该语法格式中,前面的语法和上面介绍的内容一致,后续的“=”代表赋值,其中的“值”代表具体的数据,注意区别“==”代表为判断是否相等。在该语法格式中,要求值的类型需要和声明变量的数据类型一致。
在程序中,变量的值代表程序的状态,在程序中可以通过变量名称来引用变量中存储的值,也可以为变量重新赋值。例如:
int n = 5;
n = 10;
在实际开发过程中,需要声明什么类型的变量,需要声明多少个变量,需要为变量赋什么数值,都根据程序逻辑决定,这里列举的只是表达的格式而已。

常量

常量代表程序运行过程中不能改变的值。
常量在程序运行过程中主要有2个作用:
1. 代表常数,便于程序的修改(例如:圆周率的值)
2. 增强程序的可读性(例如:常量UP、DOWN、LEFT和RIGHT分辨代表上下左右,其数值分别是1、2、3和4)
常量的语法格式和变量类型,只需要在变量的语法格式前面添加关键字final即可。在Java编码规范中,要求常量名必须大写。
则常量的语法格式如下:
final 数据类型 常量名称 = 值;
final 数据类型 常量名称1 = 值1, 常量名称2 = 值2,……常量名称n = 值n;
例如:
final double PI = 3.14;
final char MALE=‘M’,FEMALE=‘F’;
在Java语法中,常量也可以首先声明,然后再进行赋值,但是只能赋值一次,示例代码如下:
final int UP;
UP = 1;

关于final详解

final 用于声明属性(常量),方法和类,分别表示属性一旦被分配内存空间就必须初始化(不会有默认初始化,局部变量也是如此,默认初始化只有普通的非final成员属性,对于static(无final修饰)类变量,类连接时候有默认初始化,对于像private int a;在类实例化时,构造函数默认初始为0,总之,变量必须初始化后方可用,这是java的安全之一。
final这个关键字的含义是“这是无法改变的”或者“终态的”。
那么为什么要阻止改变呢?
java语言的发明者可能由于两个目的而阻止改变:
1. 效率问题:
jdk中的某些类的某些方法,是不允许被用户覆盖的,设计者可能认为,所用方法已经是最好的方法,用户私自覆盖,或是由于疏忽而覆盖,就会影响JVM或是系统的系能;
2. 设计所需:
众所周知,有些情况必须使用final关键字,比如方法中的匿名内部类的参数传递
【修饰变量】:
final成员变量表示常量,只能被赋值一次,赋值后值不再改变。
【修饰方法】:
final方法不能被子类方法覆盖,但可以被继承。
【修饰类】:
final类不能被继承,没有子类,final类中所有方法都是final的。(如String类)

被final修饰而没有被static修饰的类的属性变量只能在两种情况下初始化(必须初始化):
a.在它被声明的时候赋值
b.在构造函数里初始化
解释: 当这个属性被修饰为final,而非static的时候,它属于类的实例对象的资源(实例常量),当类被加载进内存的时候这个属性并没有给其分配内存空间,而只是 定义了一个变量a,只有当类被实例化的时候这个属性才被分配内存空间,而实例化的时候同时执行了构造函数,所以属性被初始化了,也就符合了当它被分配内存 空间的时候就需要初始化,以后不再改变的条件.

被static修饰而没有被final修饰的类的属性变量只能在两种情况下初始化(可以不初始化):
a.在它被声明的时候赋值
b.在静态或非静态快里初始化
解释:
当类的属性被同时被修饰为static时候,他属于类的资源(类变量),在类加载后,进行连接时候,分三步: 先验证;然后准备,准备时,先分配内存,接着默认初始化;可以进行解析。最后,进行类初始化,类初始化前,必须保证它的父类已经初始化了,所以最先初始化的是超类,对于接口,不必初始其父接口。类初始化时,它把类变量初始化语句及静态初始化语句放到类初始化方法中,所以,如果无此两种语句,也就没类初始化方法,而构造函数是在当类 被实例化的时候才会执行,所以用构造函数,这时候这个属性没有被初始化.程序就会报错.而static块是类被加载的时候执行,且只执行这一次,所以在 static块中可以被初始化.

同时被final和static修饰的类的属性变量只能在两种情况下初始化(必须初始化):
a.在它被定义的时候
b.在类的静态块里初始化
c.特别对于初始化时候调用抛出异常的构造函数,初始时候注意,特别是在实现单例模式时(只能这么初始化)
如:

class A{ 
    private final static A a;
    static{
        try{
            a=new A();
        }catch(Exception e){
            throws new RuntimeException(e);          //必须有,不然不能完成常量的正确初始化
        }
    }
    private A() throws Exception{}
}

解释:
当类的属性被同时被修饰为static和final的时候,他属于类的资源(类常量),那么就是类在被加载进内存的时候(也就是应用程 序启动的时候)就要已经为此属性分配了内存,所以此时属性已经存在,它又被final修饰,所以必须在属性定义了以后就给其初始化值.而构造函数是在当类 被实例化的时候才会执行,所以用构造函数,这时候这个属性没有被初始化.程序就会报错.而static块是类被加载的时候执行,且只执行这一次,所以在 static块中可以被初始化.

java中的 final变量==常量
【final变量的变与不变】:final表示变量的值或引用不变
有人说final变量在赋值后就不可变,此变量可以是基本数据类型+String或者是对象
那么这个不变到底指的是什么呢?
这个不变指的是引用,是地址,而所引用的对象的内容仍然是可变的。
注:如果为对象,注意此时类初始化条件
就是说,这个final变量永远指向某个对象,是一个常量指针,而不是指向常量的指针。
【final关键字的具体应用】:
【final+变量】:
在实际应用中,这种形式是非常少见的。
比如logger是可以的,但是貌似并不是非常实用,或许用户仍然希望通过setter来改变logger变量。
【static+final+变量】:
常量,经常使用。
【final+方法】:
JDK中常用,但是自己并未常用。
【final+类】:
helper类经常使用。
【final用于匿名内部类的参数传递】:
在多线程测试时,经常使用。
【final用于方法的参数】:
并不常用。

Java 数组

数组时储存有多重相同变量类型的对象。然而,数字自身也是堆中的一个对象。我们将要学习如何声明,建立,初始化数组。
定义数组
1. (推荐,更能表明数组类型)
type[] 变量名 = new type[数组中元素的个数];
比如:
int[] a = new int[10];
数组名,也即引用a,指向数组元素的首地址。
2. (同C语言)
type变量名[] = new type[数组中元素的个数];
如:
int a[] = new int[10];
3. 定义时直接初始化
type[] 变量名 = new type[]{逗号分隔的初始化值};
其中红色部分可省略,所以又有两种:
int[] a = {1,2,3,4};
int[] a = new int[]{1,2,3,4};
其中int[] a = new int[]{1,2,3,4};的第二个方括号中不能加上数组长度,因为元素个数是由后面花括号的内容决定的。

数组运用基础
数组长度
Java中的每个数组都有一个名为length的属性,表示数组的长度。
length属性是public final int的,即length是只读的。数组长度一旦确定,就不能改变大小。
二维数组
二维数组是数组的数组。
基本的定义方式有两种形式,如:
type[][] i = new type[2][3];(推荐)
type i[][] = new type[2][3];
变长的二维数组
二维数组的每个元素都是一个一维数组,这些数组不一定都是等长的。
声明二维数组的时候可以只指定第一维大小,空缺出第二维大小,之后再指定不同长度的数组。但是注意,第一维大小不能空缺(不能只指定列数不指定行数)。
二维数组也可以在定义的时候初始化,使用花括号的嵌套完成,这时候不指定两个维数的大小,并且根据初始化值的个数不同,可以生成不同长度的数组元素。

Java 集合

集合类说明及区别
Collection
├List
│├LinkedList
│├ArrayList
│└Vector
│ └Stack
└Set
Map
├Hashtable
├HashMap
└WeakHashMap

  • Collection接口

Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements)。一些 Collection允许相同的元素而另一些不行,一些能排序而另一些不行。

Java SDK不提供直接继承自Collection的类,Java SDK提供的类都是继承自Collection的“子接口”如List和Set。所有实现Collection接口的类都必须提供两个标准的构造函数:无参数的构造函数用于创建一个空的Collection,有一个 Collection参数的构造函数用于创建一个新的Collection,这个新的Collection与传入的Collection有相同的元素。后 一个构造函数允许用户复制一个Collection。

如何遍历Collection中的每一个元素?不论Collection的实际类型如何,它都支持一个iterator()的方法,该方法返回一个迭代子,使用该迭代子即可逐一访问Collection中每一个元素。典型的用法如下:
    Iterator it = collection.iterator(); // 获得一个迭代子
    while(it.hasNext()) {
      Object obj = it.next(); // 得到下一个元素
    }
由Collection接口派生的两个接口是List和Set。

  • List接口

List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。
和下面要提到的Set不同,List允许有相同的元素。

除了具有Collection接口必备的iterator()方法外,List还提供一个listIterator()方法,返回一个 ListIterator接口,和标准的Iterator接口相比,ListIterator多了一些add()之类的方法,允许添加,删除,设定元素, 还能向前或向后遍历。

实现List接口的常用类有LinkedList,ArrayList,Vector和Stack。

  • LinkedList类

LinkedList实现了List接口,允许null元素。此外LinkedList提供额外的get,remove,insert方法在 LinkedList的首部或尾部。
这些操作使LinkedList可被用作堆栈(stack),队列(queue)或双向队列(deque)。
注意LinkedList没有同步方法。如果多个线程同时访问一个List,则必须自己实现访问同步。一种解决方法>是在创建List时构造一个同步的List:
List list = Collections.synchronizedList(new LinkedList(…));

  • ArrayList类

ArrayList实现了可变大小的数组。它允许所有元素,包括null。ArrayList没有同步。
size,isEmpty,get,set方法运行时间为常数。但是add方法开销为分摊的常数,
添加n个元素需要O(n)的时间。其他的方法运行时间为线性。
每个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小。这个容量可随着不断>添加新元素而自动增加,但是增长算法 并没有定义。当需要插入大量元素时,在插入前可以调用>ensureCapacity方法来增加ArrayList的容量以提高插入效率。
和LinkedList一样,ArrayList也是非同步的(unsynchronized)。

  • Vector类

Vector非常类似ArrayList,但是Vector是同步的。由Vector创建的Iterator,虽然和 ArrayList创建的Iterator是同一接口,但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了 Vector的状态(例如,添加或删除了一些元素),这时调用Iterator的方法时将抛出 ConcurrentModificationException,因此必须捕获该异常。
- Stack 类
Stack继承自Vector,实现一个后进先出的堆栈。Stack提供5个额外的方法使得Vector得以被当作堆栈使用。基本的push和pop 方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。

  • Set接口

Set是一种不包含重复的元素的Collection,即任意的两个元素e1和e2都有e1.equals(e2)=false,Set最多有一个null元素。
  很明显,Set的构造函数有一个约束条件,传入的Collection参数不能包含重复的元素。
  请注意:必须小心操作可变对象(Mutable Object)。如果一个Set中的可变元素改变了自身状态导致Object.equals(Object)=true将导致一些问题。
- Map接口

请注意,Map没有继承Collection接口,Map提供key到value的映射。一个Map中不能包含相同的key,每个key只能映射一个 value。Map接口提供3种集合的视图,Map的内容可以被当作一组key集合,一组value集合,或者一组key-value映射。

  • Hashtable类

Hashtable继承Map接口,实现一个key-value映射的哈希表。
通常缺省的load factor 0.75较好地实现了时间和空间的均衡。
增大load factor可以节省空间但相应的查找时间将增大,这会影响像get和put这样的操作。
使用Hashtable的简单示例如下,将1,2,3放到Hashtable中,他们的key分是”one”,”two”,”three”:

     Hashtable numbers = new Hashtable();
    numbers.put(“one”, new Integer(1));
    numbers.put(“two”, new Integer(2));
    numbers.put(“three”, new Integer(3));

要取出一个数,比如2,用相应的key:

Integer n = (Integer)numbers.get(“two”);
    System.out.println(“two = ” + n);

由于作为key的对象将通过计算其散列函数来确定与之对应的value的位置,因此任何作为key的对象都必须实现hashCode和equals方 法。
hashCode和equals方法继承自根类Object,如果你用自定义的类当作key的话,要相当小心,按照散列函数的定义,如果两个对象相 同,即obj1.equals(obj2)=true,则它们的hashCode必须相同,但如果两个对象不同,则它们的hashCode不一定不同,如 果两个不同对象的hashCode相同,这种现象称为冲突,冲突会导致操作哈希表的时间开销增大,所以尽量定义好的hashCode()方法,能加快哈希 表的操作。
如果相同的对象有不同的hashCode,对哈希表的操作会出现意想不到的结果(期待的get方法返回null),要避免这种问题,只需要牢记一条:要同时复写equals方法和hashCode方法,而不要只写其中一个。
Hashtable是同步的。

  • HashMap类

HashMap和Hashtable类似,不同之处在于HashMap是非同步的,并且允许null,即null value和null key。,但是将HashMap视为Collection时(values()方法可返回Collection),其迭代子操作时间开销和HashMap 的容量成比例。因此,如果迭代操作的性能相当重要的话,不要将HashMap的初始化容量设得过高,或者load factor过低。

  • WeakHashMap类

WeakHashMap是一种改进的HashMap,它对key实行“弱引用”,如果一个key不再被外部所引用,那么该key可以被GC回收。

总结

如果涉及到堆栈,队列等操作,应该考虑用List,对于需要快速插入,删除元素,应该使用LinkedList,如果需要快速随机访问元素,应该使用ArrayList。
如果程序在单线程环境中,或者访问仅仅在一个线程中进行,考虑非同步的类,其效率较高,如果多个线程可能同时操作一个类,应该使用同步的类。
要特别注意对哈希表的操作,作为key的对象要正确复写equals和hashCode方法。
尽量返回接口而非实际的类型,如返回List而非ArrayList,这样如果以后需要将ArrayList换成LinkedList时,客户端代码不用改变。这就是针对抽象编程。

同步性

Vector是同步的。这个类中的一些方法保证了Vector中的对象是线程安全的。而ArrayList则是异步的,因此ArrayList中的对象并 不是线程安全的。因为同步的要求会影响执行的效率,所以如果你不需要线程安全的集合那么使用ArrayList是一个很好的选择,这样可以避免由于同步带 来的不必要的性能开销。
数据增长
从内部实现机制来讲ArrayList和Vector都是使用数组(Array)来控制集合中的对象。当你向这两种类型中增加元素的时候,如果元素的数目 超出了内部数组目前的长度它们都需要扩展内部数组的长度,Vector缺省情况下自动增长原来一倍的数组长度,ArrayList是原来的50%,所以最 后你获得的这个集合所占的空间总是比你实际需要的要大。所以如果你要在集合中保存大量的数据那么使用Vector有一些优势,因为你可以通过设置集合的初 始化大小来避免不必要的资源开销。
使用模式
在ArrayList和Vector中,从一个指定的位置(通过索引)查找数据或是在集合的末尾增加、移除一个元素所花费的时间是一样的,这个时间我们用 O(1)表示。但是,如果在集合的其他位置增加或移除元素那么花费的时间会呈线形增长:O(n-i),其中n代表集合中元素的个数,i代表元素增加或移除 元素的索引位置。
为什么会这样呢?以为在进行上述操作的时候集合中第i和第i个元素之后的所有元素都要执行位移的操作。
这一切意味着什么呢?
这意味着,你只是查找特定位置的元素或只在集合的末端增加、移除元素,那么使用Vector或ArrayList都可以。如果是其他操作,你最好选择其他 的集合操作类。比如,LinkList集合类在增加或移除集合中任何位置的元素所花费的时间都是一样的?O(1),但它在索引一个元素的使用缺比较慢 -O(i),其中i是索引的位置.使用ArrayList也很容易,因为你可以简单的使用索引来代替创建iterator对象的操作。LinkList也 会为每个插入的元素创建对象,所有你要明白它也会带来额外的开销。
最后,在《Practical Java》一书中Peter Haggar建议使用一个简单的数组(Array)来代替Vector或ArrayList。尤其是对于执行效率要求高的程序更应如此。因为使用数组 (Array)避免了同步、额外的方法调用和不必要的重新分配空间的操作。

Java 枚举值

枚举是在 Java5.0 版本中被引进的。枚举限制了变量要有一些预先定义的值。枚举列表中的值称为枚举值。
运用枚举值可以大大减少你的代码中的漏洞。
举例来说,如果我们想为一家鲜榨果汁店编个程序,就可以将杯子的尺寸限制为小中和大。这样就可以确保人们不会定大中小尺寸之外

class FreshJuice {
   enum FreshJuiceSize{ SMALL, MEDIUM, LARGE }
   FreshJuiceSize size;
}
public class FreshJuiceTest {
   public static void main(String args[]){
      FreshJuice juice = new FreshJuice();
      juice.size = FreshJuice. FreshJuiceSize.MEDIUM ;
      System.out.println("Size: " + juice.size);
   }
}

输出如下结果:Size: MEDIUM

注:枚举可以自己声明也可以在类中声明。方法变量和构造器也可以在枚举值中定义。

Java 中的注释

Java支持单行或多行注释,所有注释中的字母都会被 Java 编译器忽略。
行注释:
//开始

块注释:
/*开始
* /结束

javadoc注释:生成javadoc时,这样的注释会被生成标准的javaapi注释,该注释可以跨多行

/**
 *
 */

Java 中的分支语句

  • break语句
    break语句有两种形式:标签和非标签。在前面的switch语句,看到的break语句就是非标签形式。可以使用非标签break,结束for,while,do-while循环,如下面的BreakDemo程序:
class BreakDemo {
    public static void main(String[] args) {

        int[] arrayOfInts = 
            { 32, 87, 3, 589,
              12, 1076, 2000,
              8, 622, 127 };
        int searchfor = 12;

        int i;
        boolean foundIt = false;

        for (i = 0; i < arrayOfInts.length; i++) {
            if (arrayOfInts[i] == searchfor) {
                foundIt = true;
                break;
            }
        }

        if (foundIt) {
            System.out.println("Found " + searchfor + " at index " + i);
        } else {
            System.out.println(searchfor + " not in the array");
        }
    }
}

这个程序在数组终查找数字12。break语句,如上的粗体,当找到只时,结束for循环。控制流就跳转到for循环后面的语句。程序输出是:

Found 12 at index 4
无标签break语句结束最里面的switch,for,while,do-while语句。而标签break结束最外面的语句。接下来的程序,BreakWithLabelDemo,类似前面的程序,但使用嵌套循环在二维数组里寻找一个值。但值找到后,标签break语句结束最外面的for循环(标签为”search”):

class BreakWithLabelDemo {
    public static void main(String[] args) {

        int[][] arrayOfInts = { 
            { 32, 87, 3, 589 },
            { 12, 1076, 2000, 8 },
            { 622, 127, 77, 955 }
        };
        int searchfor = 12;

        int i;
        int j = 0;
        boolean foundIt = false;

    search:
        for (i = 0; i < arrayOfInts.length; i++) {
            for (j = 0; j < arrayOfInts[i].length;
                 j++) {
                if (arrayOfInts[i][j] == searchfor) {
                    foundIt = true;
                    break search;
                }
            }
        }

        if (foundIt) {
            System.out.println("Found " + searchfor +
                               " at " + i + ", " + j);
        } else {
            System.out.println(searchfor +
                               " not in the array");
        }
    }
}

程序输出是:

Found 12 at 1, 0
break语句结束标签语句,它不是传送控制流到标签处。控制流传送到紧随标记(终止)声明。

  • continue语句

continue语句忽略for,while,do-while的当前迭代。非标签模式,忽略最里面的循环体,然后计算循环控制的boolean表达式。接下来的程序,ContinueDemo,通过一个字符串的步骤,计算字母“p”出现的次数。如果当前字符不是p,continue语句跳过循环的其他代码,然后处理下一个字符。如果当前字符是p,程序自增字符数。

class ContinueDemo {
    public static void main(String[] args) {

        String searchMe 
            = "peter piper picked a " +
              "peck of pickled peppers";
        int max = searchMe.length();
        int numPs = 0;

        for (int i = 0; i < max; i++) {
            // interested only in p‘s
            if (searchMe.charAt(i) != ‘p‘)
                continue;

            // process p‘s
            numPs++;
        }
        System.out.println("Found " +
            numPs + " p‘s in the string.");
    }
}

这里是程序输出:Found 9 p’s in the string.
为了更清晰看效果,尝试去掉continue语句,重新编译。再跑程序,count将是错误的,输出是35,而不是9.

标签continue语句忽略标签标记的外层循环的当前迭代。下面的程序例子,ContinueWithLabelDemo,使用嵌套循环在字符传的字串中搜索字串。需要两个嵌套循环:一个迭代字串,一个迭代正在被搜索的字串。下面的程序ContinueWithLabelDemo,使用continue的标签形式,忽略最外层的循环。

class ContinueWithLabelDemo {
    public static void main(String[] args) {

        String searchMe 
           = "Look for a substring in me";
        String substring = "sub";
        boolean foundIt = false;

        int max = searchMe.length() - 
                  substring.length();

    test:
        for (int i = 0; i <= max; i++) {
            int n = substring.length();
            int j = i;
            int k = 0;
            while (n-- != 0) {
                if (searchMe.charAt(j++)
                    != substring.charAt(k++)) {
                    continue test;
                }
            }
            foundIt = true;
                break test;
        }
        System.out.println(foundIt ?
            "Found it" : "Didn‘t find it");
    }
}

这里是程序输出:Found it

  • return语句

最后的分支语句是return语句。return语句从当前方法退出,控制流返回到方法调用处。
return语句有两种形式:一个是返回值,一个是不返回值。
为了返回一个值,简单在return关键字后面把值放进去(或者放一个表达式计算)
return ++count;
return的值的数据类型,必须和方法声明的返回值的类型符合。
当方法声明为void,使用下面形式的return不需要返回值。
return;

脚注

转载请注明出处,该博客同步更新在我的个人博客网站。1.


  1. 我的博客网站:www.klsstt.com. ?

java编程思想总结(二)

标签:

原文地址:http://blog.csdn.net/klsstt/article/details/51782563

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!