Thinking in java 笔记
9月25日
Thinking in java 笔记
第一章 对象导论
其实这章介绍的是oop的思想,知道什么是抽象、接口、继承等等,其实这些我觉得没有必要专门提出来写一章,这个我就不介绍了
在以后的学习中,这些知识是会在里面融会贯通的。
第二章 万事万物皆对象
在java程序中,万事万物皆对象,即使是java程序本身,也是一个对象
一、Reference是操纵对象之钥匙
c语言中是使用指针来操纵对象的,但是java呢?用的是reference来操纵对象,我习惯把他叫做句柄,句柄和对象的关系就想是电视遥控器和电视机的关系一样,既然是这样,那么遥控器和电视机都是可以独立出现的
例如:String name;
这个java语句只会产生句饼(遥控器),并不产生实际的对象(电视机),就想你老婆还没生孩子之前你们就把名字给取好了一样,句柄并没有连接到实际的对象上。这个样子写代码是不推荐的,一个没有指向对象的句柄在调用的时候编译器会抱错,应当使用String name="baby";,或者使用String name =new String("baby");这里new的意思是产生一个string类型的对象,并且这个string叫做baby。这2个方法都可以实现对象的建立。
二、所有的对象都需要你来建立
1、储存在那里
a、寄存器 这里是核心的存储空间,我们是没办法操纵的
b、栈 (stack )这里的存取速度快,效率高,因为这里要求被存储的数据有具体大小和存活时间限制,使用弹性小,这里一般存储的是我们的对象句柄,而对象是不存在这里的
c、堆 (heap) 这里是通用的存储空间,他比stack好在编译器不需要知道实际在heap中存储数据的大小,也不知道这个空间需要分配多长时间,弹性好,所以用来存储对象,但是速度要比stack慢很多
d、静态存储空间(static storage)这里是存放被声明为static的特定成员,java对象本身是不会分配在这里的
e、常量储存空间 这里存放的是程序中的常量,常量值不会改变,最安全
f、non-ram 流或者是持久话对象
2、基本数据类型
boolean char byte short int long float double void 基本数据类型的数据是不用new 来创建的,直接int i=0,不使用heap空间,他是被放在stack中的,速度快!但是假如你要是想用heap来存储基本数据类型的话,就要使用该类型的外覆类来实现了 例如Integer i= new Integer("0");
注意!String不是基本数据类型,她是对象!从他的定义方法就可以知道了!
3、数组(array)
java中的数组使用和定义上要比c中的数组更安全,当你在定义数组的时候其实产生的是一个储存对象句柄的数组,而每一个句柄所指向的值回被设定为null,也就是不指向任何对象
三、你不需要摧毁对象
1、基本类型生存范围
java中基本类型的生存范围是由一对大括号决定的,在生存空间内定义的变量,只能用于生存空间结束之前
{
int i=1;
{
int i=100;//错误!这样的定义在java总是不允许的!编译器会认为i已经被定义过了
}
}
2、对象的生存范围
对象拥有的寿命和基本类型是不一样的,当你使用new来产生一个对象的时候,即使离开了大括号,该对象还是存在的
{
String name =new Sting("baby");
}
句柄name会在大括号的生存空间之外消失的,但是他所指向的string对象却还在继续占用着内存,但是大家会认为大量的无用对象会占用大量的内存,java中是怎么解决的呢?他使用的是垃圾回收机制,垃圾回收器会在特定的时间检查使用new创建的对象,假如这些对象已经没有句柄指向他们,那么他就回把无用的对象清理掉。
四、建立新的数据类型 class
java中既然一切全是对象,那么是什么来限制对象的属性呢?通过使用类。java中使用class关键字来自己定义一个类
例如:class women{ //class body}这样你就定义一个women 类,当然这个类没有任何属性
1、数据成员和方法
一个类中,存在2中成员,一个是数据成员,一个是方法。数据成员可以是基本数据类型,也可以是对象,而基本数据类型在声明的时候系统会自动的给他赋予一个初始值
五、方法、参数、返回值
一个合法的方法包括名称、参数、返回类型、方法体 例如
void name(int i)
{
return;
}其中 名称name() 参数int i 返回类型 void 方法体 {},对于一个class而言,名称+参数的组合必须是唯一的,参数也可以是空的,有一个叫test的对象允许你调用一个返回值为string的方法getTest(),则 String name = test.getTest(); name的类型一定要和返回值的类型相同。
在向一个方法传递一个对象的时候,其实传递的是该对象的句柄(基本数据类型除外),而传递的对象类型一定要和方法中接受参数的参数类型相同。当你不需要方法给你返回什么东西的时候,你可以把该方法的返回类型设置为void,而此时方法中的return就是用来离开方法的,不需要等到他执行完毕,如果方法的返回类型不为void的时候,你可以使用return 返回一个和返回类型一样的值
打造第一个java程序
名称的可视性
名称问题有些人觉得不是什么大问题,我开始也觉得那不是个什么大问题,但是当你有一天写了很多的类时,你就发现,名称其实真的很重要,假如你有这么一个类,他需要调用其他几个类, 当这几个被类名相同时,问题就出现了,那么
怎么区分他们,并且使他们的名称不冲突呢?毕竟我们不可能把每个声明过的类的名字一一记住,以便在下次声声明其他名称时,加以区分。这个时候我们就需要使用包(package)了,一个包就是一个命名空间。命名空间的使用规则是:反转internet域名,例如,我的blog是blog.csdn.com/maoerzuozuo你可以在类的开头使用package maoerzuozuo.com.csdn.blog,这样就好了~每个包都是一个独一无二的命名空间。需要注意一点:当使用package说明一个包时,该包的层次结构必须和文件目录的结构相同!就想c:\maoerzuozuo\com\csdn\blog
使用其他组件
包定义了之后一定要使用的,怎么使用呢?在文件的开头使用import关键字,假如我要导入我开发的一个叫hello.class组件,我只要import maoerzuozuo.com.csdn.blog.hello;就导入了我所创建的包,当然你也可以偷懒,用import maoerzuozuo.com.csdn.blog.*;
导入该文件夹里所有的包(也许你有的包根本用不上),但是这样有个弊端,就是在编译的速度要比直接指明包的编译速度要慢。
关键字static(静态的)
一个class只有在你使用new来产生对象时,他的函数才能被外界使用,但是也有2中情况是用上面的方法无法实现的。
1、不管产生多少的对象或没有对象产生对象时,一些特定的数据存储只有一份;
2、类中的某个函数不想和对象绑定在一起,既我不想产生对象,但是我还想用类中的一个函数;
一般情况下, 你要使用一个非静态(non-static)的成员的话,必须先产生一个对象使用对象来调用这个数据或函数,所以你必须知道这个函数/数据属于哪个对象才行,因为static是不用产生对象就可以使用的,所以在static的函数中不能直接调用non-static的函数或变量。
解决1、把static关键字摆在成员变量或函数定义之前,就可以使他们变为静态的。
class StaticDemo
{
static int i=888;
public static void main(String args[])
{
StaticDemo sd1=new StaticDemo();
StaticDemo sd2=new StaticDemo();
System.out.println(sd1.i);//888
System.out.println(sd2.i);//888
StaticDemo.i++;
System.out.println(sd1.i);//889
System.out.println(sd2.i);//889
}
}
现在即使你产生n个StaticDemo对象,但是i只有原始的一份,不管你是sd1.i还是sd2.i,其实就是同一个i,全部引用自这个StaticDemo.i,所以,只要改变StaticDemo.i内存储的数据,这些sd1和sd2的i都会改变,因为他们的i的句柄全部指向的是StaticDemo.i这一个内存空间,就相当于,有一个人在a公司工作,还在b公司兼职,而他假如死掉了,则同时影响2家公司,就是这个意思,同样的道理也适用于static的函数
解决2、要想不产生对象就能使用函数,这样需要在函数名前加上static
class StaticDemo
{
public static void show(String s)
{
System.out.println(s);
}
public static void main(String args[])
{
show("one");//调用方法1
StaticDemo.show("two");//调用方法2
new StaticDemo().show("three");//调用方法3
}
}
对于调用方法1,其实他隐藏了一个关键子,就是this,他的完整形式应当是this.show("one"),这个this的用法以后会学到
对于调用方法2,使用的是className.method()的形式,这个也就是static的函数调用的典型形式,non-static的函数是不能使用这样的方法调用的!
对于调用方法3,这个方法就是我们调用函数的一般方法,创建对象,由对象调用函数,这个方法对于static和non-static是同样适用的。某个成员变量在声明为static的时候,其建立的方式有很大的变化,但是static的函数变化不大,static函数最大的一点用处就是可以在不建立对象的情况下,调用函数,就像我们经常见到的main函数一样。
你的第一个java程序
java程序默认的回把java.lang下的包导入到你所创建的文件中,我们没有必要再使用import来导入。一个public的class的名称一定要和文件名称是一样的,并且一个class里面只允许有一个public的class,附则程序是编译不过去的。如果你要运行这个类的话,那么这个类中一定要有一个main()函数,他的固定格式为public static void main(String args[]),其中,public表示这是一个公开给外界使用的函数,并且是个static的不允许有返回值,而传入main()的参数必须是个String对象数组,即使你从来没有过,这个args[]的string数组可以存储cmd的参数。
编译与执行
使用javac 文件名.java来编译java文件,使用java className来执行className这个类,这里要注意2点,一个是当你使用java命令执行一个类时,这个类必须要有main函数;第二个className不一定等于文件名,一个java文件中假如有public类,那么这个类名必须要和文件名相同,其他情况你可以随你自己的意思起名字
注释及内嵌文档
//注释单行 /*.......*/注释多行,多行注释内不能嵌套多行注释。
寓文档于注释
javadoc命令可以将内嵌在程序代码中的文档提取出来,生成html格式的文件,使用浏览器就可以查看。
语法
这个部分我就跳过去了,有兴趣的朋友自己看看,很简单的
编码风格
类名在编写的时候,应当第一个字母大写,如果名称是由多个单词组成,则把这些个单词并在一起写,并且把他们的第一个字母大写 例如 public class MaoErZuoZuo
本章总结:
这一章总算ko了,呵呵~其实这章讲的不难,大家就是要仔细看书,好好体会tij的精髓
本章习题解答
这章的习题总体不难,惟独有一个题是运用了后面学习的知识,我们就把他作为难题来对付好了
"撰写某个程序,使他能够接受由命令行传入的3个引数,为此,你需要对代表命令行引数的string数组进行索引"
public class Solve
{
public static void main(String args[])
{
System.out.println(args[0]);
System.out.println(args[1]);
System.out.println(args[2]);
}
}
这个程序可以接受3个引数,并且把他显示出来,有的人会问了:我们怎么把引数传递进来呢。大家在运行时,要在java Solve后面加个空格,在加三个引数,每个使用空格隔开,例如 java Solve aaa bbb ccc这样程序就会接受到这3个引数,并且把他显示。当你输入引数和接受引数的数量不符时候,会抱ArrayIndexOutOfBoundsException的错误,希望大家注意!</P< p>
第三章 控制程序流程
在java的世界中,对象和数据的处理是通过运算符,而选择和判断则是靠控制语句来实现的
使用java运算符
运算符的2个用处,1、运算符接受引数,并且产生新值,例如 int a=1+1;2、运算符也可以改变操作数的值 例如 i++;
大多数的运算符都是可以作用与基本数据类型之上的,但是=、==、!=是例外,他们可以作用于任何对象之上。
优先顺序
这个其实我自己也很头疼的!所以我向来不记什么运算符的优先顺序,在搞不清楚的地方就加上括号,这样不但你自己看起来很明了,出错率也低,别人来看你的代码也是能清楚明白的
赋值和指派
赋值的意义是取得运算符右边的值(任何常量、变量、能产生数值的表达式),并将该值传递给左边,使用运算符=号因为基本数据类型存储的是实际的数值,并非句柄(也可以理解我c++中的指针),a=b;这句是把b这个具体数值传递给a这个变量,当你改变a的时候,b这个数值并不会随着你的a的改变而改变,但是当你操作对象的时候就容易出现和上述现象相反的事情。当你在操作对象的时候,实际上操作的是对象的句柄,当你把某个对象指派给另一个对象时,
实际指派的是句柄,例如
class one
{
int i=0;
}
class two
{
public static void main(String args[])
{
one o1=new one();
one o2=new one();
o1.i=10;
o2.i=20;
System.out.print("o2.i="+o1.i);
System.out.println("o2.i="+o2.i);
o1=o2;
System.out.print("o2.i="+o1.i);
System.out.println("o2.i="+o2.i);
o1.i=30;
System.out.print("o2.i="+o1.i);
System.out.println("o2.i="+o2.i);
}
}
class one在two中被创建2个对象,并且分别回被赋值为10 和20。输出当然就是10和20,接着把o2指派给o1,输出肯定是20 和20,但是奇妙的事情在第3次赋值的时候产生了,当我们把o1.i的值改为30的时候,发现为什么我们的o2.i也变成30了?我们并没有改变他的值啊!这是因为o1和o2中都含有同一个句柄,原先的o1所存储的句柄被覆写了,地址指到了和o2一样的内存空间,而他原先的指向的那个内存空间在适当的时候回被垃圾回收机制给回收了,其实这个过程就发生在我们以为不会有问题的第2次赋值中!以上的现象就叫做别名现象,这个在Thinking in Java的附录a中有专题讲到!如果我们不想发生这样的事情,我们可以使用o1.i=o2.i这句话来进行第2步,这样的写法可以保证2个对象的相互独立,但是这个并不是一个好方法,这样直接操作对象内的数据会导致混乱,并且和oop的思想相违背,更好的方法在附录a中有。
调用函数时的别名问题
class one
{
int i=10;
}
class two
{
static void hello(one o)
{
o.i=20;
}
public static void main(String args[])
{
one someone=new one();
System.out.println(someone.i);
hello(someone);
System.out.println(someone.i);
}
}
我们的java程序会在hello()函数的生存空间之内为我们创建一个名字叫个o的one的实例对象,用于接受外界传递进来的引数,但是我们使用上面的方法,传递进去的其实也只是一个someone的句柄,而hello()之内的那个名字叫个o的对象的i的更改也会影响到超出hello生存空间之外的someone中的i,真是郁闷啊!
数学运算符
这里我们要注意一个问题就是整数的除法运算所得结果会把小数部分忽略,注意不是四舍五入!什么是简略运算符?简略运算符是在运算符之后紧跟一个=号,这个方法使用于java中的所有运算符,,例如 把x+10的值从新赋值给x,你就可以用x+=10这种简略形式。具体的数学运算符的例子我就不给大家举了,因为这个很简单,和我们小学学习的数学运算没有什么差别
一元运算符
负号(-)和正号(+)都是一元运算符
递增和递减
递增(++)和递减(--)他们都有2中形式,一个是前缀(++i),一个是后缀(i++)需要注意的是,这2个方法是有差别的,在使用前缀的时候,是先进行前缀的运算,然后把值传递给i,然后i再参与后面的运算,而使用后缀时候,是先把i参与运算,再将i 进行后缀的运算,例如
public class test
{
public static void main(String args[])
{
int i=0;
System.out.println(++i);
System.out.println(i++);
System.out.println(i);
}
}
答案是1、1、2 先进行自加,然后把值显示(1)第二次显示是先把i的值显示(1),在自加(2),但是自加的没显示因为自加的值参加下次的运算,也就是第三次显示2的原因
逻辑运算符
逻辑运算符 AND(&&)?? OR(||)? NOT(!)? 都会得到一个boolean值,且他们只能用于boolean身上。逻辑表达式中的boolean无法使用类似于c/c++中的数值代替。注意,boolean被用于一个预期会出现string的地方,其值会自动转换为适当的文本形式,并且假如2个比较的基本数据类型不相同,也是可以比较的~例如10和10.0d,结果也是会返回true的
短路式的核定
这个的意思就是逻辑表达式中的部分语句可能因为逻辑运算符的使用不当,导致有些语句并没有经过判断,只要大家细心点,掌握知识牢靠就没什么问题~
位运算符
位运算符可以让你操作整数基本数据类型中的个别bit位,切记是整数基本数据类型!位运算符直接造作的是数据中的0和1,直接面向硬件,所以有的人说java无法控制底层硬件,这个说法是不正确的,你完全可以直接控制硬件~好象asm一样~
位运算符
AND(&)会在2个输入位全为1时,产生一个输出位1,否则为0;
OR(|)会在2个输入位有任意一个为1时,产生一个输出位1,当2个输入位全部为0时,输出0;
XOR(^)会在2个输入位上有且只有一个输入位为1时,产生输出位1;
NOT(~)也叫做"一的补数运算符",是一个一元运算符(其他的是2元预算符),他仅仅接受一个引数,并且产生相反位
注意,位运算符和逻辑运算符很想。但是他们是有区别的,我曾经见过一个招聘题目,其中就有让你阐述他们的区别,除了’~‘之外,任何一个位运算符都可以和赋值运算符=号合用,类似于+=
boolean,你可以在他身上执行除了not之外的任何一个位运算符;对于boolean而言,位运算符和逻辑运算符的唯一区别就是位运算符不做短路式,最后boolean是无法做位移运算的
位移运算符
位移运算符也是用来操作位的,也是只能作用在整数基本数据类型上在java中采用补码表示二进制数,在补码表示中,最高为为符号位,正数符号位是0,负数符号位是1,补码的规定如下:
对于正数来说,最高位是0,其余各位代表数值本身的二进制数;
对于负数来说,把该数的绝对值的补码按位取反,然后对整个数+1,取得该数的补码。如-1的补码为11111111,-1的绝对值补码是00000001,按位取反11111110,再加1,11111111
左移运算符(<<)会左操作数向左迁移,迁移的位数由右操作数决定(左移后,低位补0)a=a<<2,使a的各个二进制位左移2位,右补0,若a=00001111则a<<2=00111100,高位左移后溢出的位舍弃掉了在不产生溢出的情况下,左移一位相当于乘2,用这种方法来实现乘法,要比乘法运算快很多,所以有的公司在效率题目上,会出这样的题。
右移运算符(>>)会使左操作数向左迁移,迁移的位数由右操作数决定,面对带有正伏负号的迁移,右移运算符先会采用一种叫符号扩展的措施:如果原值为正数,高位补0;如果原值为负数,则高位补1。
此外,java中还增加了无正负号的右移运算符(>>>)采用的是零扩展措施:无论原值是正还是负。一律在高位补0,如果你操作的位移对象是char 、byte、short 的话,在位移进行的时候,会把他们先提升为int,才进行位移,当然结果也是int的。位移运算中位移的位数,对于int类型的数据来说,只有低位的5个bit位是有用的,对于long来说,只是低位的6个bit位是有用的。
位移运算符和其他运算符一样,也是可以和=号并用的,但是当在byte和short上进行无正负号的>>>=时候就有问题了,因为他们会先被提升为int,然后右移,再赋值回来,但是当他们赋值回来的时候,超过他们的容量大小的高位会被截去,就会产生很奇怪的数字-1
public class test
{
public static void main(String args[])
{
int i=-1;
long l=-1;
short s=-1;
byte b=-1;
i>>>=10;
System.out.println(i);//1
l>>>=10;
System.out.println(l);//2
s>>>=10;
System.out.println(s);//3
b>>>=10;
System.out.println(b);//4
b=-1;
System.out.println(b>>>10);//4
}
}
答案是?4194303、18014398509481983、-1、-1
4194303需要注意的是这个答案,因为第4个移位后的结果并没有传回b,所以才能显示正确的答案,这个答案之所以和第一个是一样的,因为b被提升成int b了,所以答案和int i的是一样的!
if-else 三元运算符
这个好象是java中唯一的一个3元运算符,呵呵~他的格式是
boolean-exp?value1: value2
如果boolean-exp的判断是true 则执行value1,如果为false,则执行value2,这个和if-else语句是一样的~但是他要比
if-else语句要精练,并且执行的效率要比他高!
需要注意的是:value2中的语句是要带有;号的,并且不能放进去System,out.println();之类的语句的,我们是用3元运算符要的是他的运算结果值,并不是if-else所能实现的控制程序流程。
逗号运算符
在java中,唯一能放;号运算符的地方,就是for循环中,这个我们会在以后讲到应用于string身上的operator+这个问题我在我的"java初学者容易出现的运算符问题"中已经提到了~在java中,假如+号在string之前出现,执行的是运算,而要是在string 后出现,则执行的是字符连接,例如
public class test
{
public static void main(String args[])
{
int x=1,y=2,z=3;
String s="string";
System.out.println(x+y+z+s);
System.out.println(s+x+y+z);
System.out.println(x+y+s+z);
}
}
显示6string
string123
3string3??
转型运算符
转型分为2类,自动转换和强制转换,自动转换就是系统自动进行的宽化转换,例如byte类型的b +1时,系统会自动把他的byte类型转化为int类型,你可以使用byte b=b+1;看看就知道了,系统就会告诉你possible loss of precision,因为你在加1的时候,b的值已经是int类型了,你也没办法再赋值回b了,系统在比int小的数据类型上进行运算时会把他们的值提升为int,而在和long运算时会提升为long,以此类推。所谓的强制转换,就是你告诉编译器,我知道b是个int类型但是他的表达值并没有超过byte的范围,你就放心的转化吧~也就是这么一句话:b=(byte)(b+1);他就会把int缩小为byte,但是假如你运算完的值大于了原来类型表达范围,但是你还要强制转换,发生了内存溢出,那么溢出的bit位会被抛弃,发生数据丢失现象。java中只允许除了boolean之外的基本数据类型的类型转换,这个要记牢
字面常量
一般而言,当你将某个常量放到程序中,编译器很清楚的知道要将他制成什么类型,但是有的时候为了避免模糊不清,我们就可以为常量搭配一些特殊的字符,来引导编译器的正常判断,在常量值后添加l/L指的是long类型,添加f/F指的是float类型,d/D指的是double类型。而十六进制的表达方法是以0x/0X开头,八进制是以0开头,但是java中不提供二进制的表达方法,你需要注意这几个类型所能表达的十六进制最大值
char 0xffff????? byte 0x7f??????? short? 0x7fff?? int? 0x7fffffff
java没有sizeof运算符
再谈优先级
还是那句话,不清楚的时候加括号~嘿嘿~也不用记那些烦琐的优先级了~
最后一点:当2个最够大的int相乘时所发生的溢出而导致的异常,java是不会在编译期或者是运行期报告的~这个应该算是他的一个小bug了。
流程控制
java中的流程控制语句有 if-else whlie do-whlie for switch-case 但是没有提供goto,他在java中是保留字,不是关键字(以后可能会有哦~)
true和false
java中不支持用数字表示boolean值,如果你一定要使用,请先以表达式将他转换为boolean值,例如if(a==0)
if-else
这个流程控制语句恐怕是我们最常用的了,其中else可有可无可以使用
if(boolean) if(boolean)
statement statement
else
或者 statement
其中statement可以是一个单独的语句,也可以是好几个语句组成的复合语句,当使用复合语句的时候一定要用大括号括起,而单独的语句,可适可不适
举个使用的例子吧
public class test
{
public static void main(String args[])
{
int i=0;
if(i>=0)//这里需要注意的是千万不要加;号
{
System.out.println("i>=0");
}
else
{
System.out.println("i<0");
}
}
}
return
关键字return的作用:指明函数需要传回的值,并且立即传回。这里需要知道2点,返回值的类型的表达范围要等于或者小于函数的返回类型,例如,函数返回值是int,你如果返回一个double的数值,编译器就会抱错,反之,则不会
public class test
{
public static double go()
{
if(1>0)
{
System.out.println("hello");
return 100l;//返回一个long类型的100
//!System.out.println("hello");注意在return的后面不可以再加任何语句,return就是一个程序块的终结点
}
else
return 100f;//返回一个flout类型的100//注意使用了if-else分别来返回一个值的时候,切记在if和else后面都要加上return
}
public static void main(String args[])
{
System.out.println(go());
}
}
你还可以使用不加返回值的return;来跳出函数,但是注意,如果你要使用这样的方法,那么函数的返回值类型那里一定要是void
迭代
while do-while for 这几组关键字用来控制循环,他们有的时候也会被归结在迭代语句中。
while
例子 while(boolean)
{
//......
}//持续执行内部代码,直到让boolean变成false为止
do-while
例子 do
//........
while(boolean)
//......
他和while的唯一差别是,do-while至少会被执行一次,哪怕一开始都不满足true运行的条件,至少执行一次的语句要放在do的里面
for
for循环会执行如下几个步骤 1、初始化变量 2、进行条件判断 3、每执行完一次,进行一次步进
例如for(int i=0;i<10;i++)会先初始化i,判断i是否小于10,如果小于执行for循环体内的语句,并且把i的值加1,直到i大于10的时候,退出。其中的3步都可以为空的,即for(;;),则他的意义和while是一样的。
你还可以在for语句中定义多个变量,但是他们的类型一定要一样,这种定义的方法式能且只能在for中使用
for(int i=0,j=1;i<10&&j!=11;i++,j++)
要注意,在for括号里面定义的变量,只能在for循环的表达控制式中使用和存活,而不是在循环体的大括号内的!
break和continue
在迭代语句中,你可以使用break和continue来控制循环语句,他们的唯一区别就是,break会跳出循环,不去执行剩余部分,而continue会停止当前的迭代,回到循环的启示出,开始下一个迭代。
public class test
{
public static void main(String args[])
{
for(int i=0;i<100;i++)//2
{
if(i==88)
break;//这句话导致i的值永远不会大于88,因为如果大于88的话,程序就会跳出,到1的哪个位置了
if(i%2!=0)
continue;//当i是个偶数的时候,程序才会向下执行,打印出i的值,如果不是偶数,则跳到2处,把i++再重新循环
System.out.println(i);
}//1
}
}
其实哪个i==88是个废话,完全可以在for循环中就能控制,我只不过举了个例子而已,呵呵
臭名朝著的"goto"
从第一个程序语言诞生的时候就有goto这个关键字,然而,由于大多数程序员的使用不当,而引发出来很多问题。这不是goto的问题,就想枪支一样,好人用了就是武器,坏人用了就是凶器~嘿嘿~
java中没有goto,但是有和goto功能类似的语句-----标记,可以执行类似跳跃功能,但不是真正的跳跃,而是一种中断迭代语句的方式他可以和break、continue共用,共用的效果是可以中断所有进行中的嵌套循环,直到label的所在处。标记其实就是个后面紧跟冒号的标示符,例如 thisislabel :。在java中唯一能放label的地方就是迭代语句开始之前,请不要在label和迭代语句之间加入任何内容。
使用规则
1、continue会跳跃到他所在的内层循环顶端,继续执行
2、contine label会跳跃到label所在的位置,然后重新进入循环
3、break会跳离循环
4、break label会跳离label所在的位置
while 中使用label例子
public class test
{
public static void main(String args[])
{
int i=0;
oneLabel:
while(true)
{
System.out.println("this is while method");
while(true)
{
i++;
System.out.println(i);
if(i==1)
{
System.out.print(i);
System.out.println("continue");
continue;
}
if(i==3)
{
System.out.print(i);
System.out.println("continue oneLabel");
continue oneLabel;
}
if(i==5)
{
System.out.print(i);
System.out.println("break");
break;
}
if(i==7)
{
System.out.print(i);
System.out.println("break oneLabel");
break oneLabel;
}
}
}
}
}
for使用label例子
public class test
{
public static void main(String args[])
{
int i=0;
oneLabel:
while(true)
{
System.out.println("this is while method");
for(;i<8;i++)
{
System.out.println(i);
if(i==1)
{
System.out.print(i);
System.out.println("continue");
continue;
}
if(i==3)
{
System.out.print(i);
System.out.println("continue oneLabel");
i++;//continue oneLabel会跳出for循环,则没有进行一次完整的迭代,所以累加不会发生,为了祢补,我们在这里把i+1
continue oneLabel;
}
if(i==5)
{
System.out.print(i);
浙公网安备 33010602011771号