一、什么是变量
定义在方法中的变量、定义在方法参数中的变量,定义在for循环中的变量都是“局部变量”,只能在有限的范围内被使用。定义在全局里面,可以被全局使用的叫做全局变量。
二、实体
1、实体包括:
数组和对象,数组也可以称之为对象!
2、注意:
如果实体是一个数组,那么变量并不是数组本身,而是一个变量指向一个数组的地址,也就是说,如果变量是x的话,那么x的值就是一个数组的地址,这个地址指向堆里面的一个数值,然后x就有一个数值了。
三、java内存常识
java在运行的时候一共在内存中开辟了五片内存空间,分别是:方法区、本地方法区、寄存器、栈内存、堆内存。
1、栈内存:
用于存储局部变量,当数据使用完后,所占用的空间会被自动释放。
2、堆内存:
(1)、数组和对象,通过new建立的实例都存放在堆内存中。
(2)、每一个实体都有内存地址值。
(3)、实体中的变量都有默认的初始化值。
(4)、实体不再被使用的时候,会在不确定的时间内被垃圾回收机制回收。
(5)、堆内中的实体是用来封装数据的,而这些数据都是有默认的初始化数值。比方说,我们定义了一个数组之后,对没有进行任何定义的数组进行一个输出的话,我们会发现这个没有任何数据的数组还是有一个默认的初始化的数值的,那就是都是0,布尔型的数据,默认的数值是false。
3、注意:
(1)、凡是局部变量都在栈内存中的!
(2)、堆里面存放的就是实体!
(3)、栈是自动释放内存的,而堆是使用的垃圾回收机制去除堆内存中的垃圾信息的!
4、“字节”和“位”的关系:
一个字节是8位,也就是8个二进制单位,一般一个汉字占用2个字节,也就是16位,但是这种情况是不确定的,字节也叫Byte,是计算机数据的基本存储单位。
8bit(位)=1Byte(字节)
1024Byte(字节)=1KB
1024KB=1MB
1024MB=1GB
1024GB=1TB
其中:K是千 M是兆 G是吉咖 T是太拉。在电脑里一个中文字“一般”占两个字节,也就是16位。注意,是一般!
四、方法(函数)
1、方法(函数)的特点:
(1)、定义函数可以将具有某些功能的代码进行封装便于对该功能进行复用 。
(2)、函数只有被调用的时候才可以被执行。
(3)、函数的出现提高了代码的复用性。
(4)、对于函数没有具体返回值的情况,返回值类型用关键字void表示,那么该函数中的return语句如果在最后一行中可以“省略”不写的。
2、注意:
(1)、函数中只能调用函数,不可以在函数内部定义函数。
(2)、定义函数时,函数的结果应该返回给调用者,交给调用者处理。
(3)、void类型就是没有具体返回值的关键字!可以省略return不写,但是写出来也不算错!
3、方法(函数)的重载:
当定义的功能相同,但是参与运算的内容不同,那么,这时候就定义一个函数名称以表示其功能,方便阅读,而通过参数类型或者个数的不同来区别多个同名函数。
方法(函数)的重载也就是说定义的方法(函数)的名字一样,但是方法的类型或者是方法参数的个数不同,然后在调用的时候,参数部分对应相应的参数类型或者是参数个数即可实现方法的重载。
这是一道常用考题,下面哪些方法(函数)使用了重载:
void show(int a,char b,double c){}
(1)、void show(int x,char y,double z){}//没有重载,因为与原函数一样的
(2)、int show(int a,double b,char c){}//重载了,因为参数的类型不同,注意的是:重载和返回的类型没有关系
(3)、void show(int a,double b,char c){}//重载了,因为参数的类型不同,注意的是:重载和返回的类型没有关系
(4)、boolean show(int c,char b){}//重载了,因为参数的个数不同
(5)、void show(double c){}//重载了,因为参数的个数不同
(6)、double show(int x,char y,double z){}//没有,和原函数一样的,注意的是:重载和返回的类型没有关系
五、数组
1、一维数组:
int[] arr=new int[3];
数组arr并不是int类型的,之所以前面说的是int类型的是因为数组内部的元素是int类型的,但arr不是int类型的,arr是一个数组,所以是数组类型的,自己一定要记住这一点!
2、注意:
(1)、数组是一种单独的数据类型。
(2)、如果一个变量定义成null的话,那么就不再指向数组了。
3、一维小注意:
int[] arr=new int[]{3,6,5,1,8,9,67};
System.out.println(arr);
输出结果并不是数组中元素的内容,而是一个类似“[I@de6ced”的内容,实际上,数组想要输出其中元素的内容的话,必须使用循环进行遍历操作,逐个数出,直接用输出语句输出的是引用的内存地址。其中“[”是数组的大括号,I是int类型的,@后面的是数组的内存存放地址,上面的数值实际上是由哈希算法算出来的十六进制的哈希值!
4、二维数组:
int arr[3][2]
意思就是有三行两列,其中3是arr数组的长度,我们可以用arr.length得出结果,上面的意思就是我一个二维数组中有3个元素,其中每一个元素中有2个元素,可以用下面的图表示:
**
**
**
5、二维数组的小面试题:
int[] x,y[];
这样的意思就是说:前面的x是一维数组,后面的y是二维数组
拆开写出来就是这样的:
int[] x;
int[] y[];
注意区别一维数组和二维数组的定义形式!
6、数组排序:
最有效的升序排序方法:使用Arrays.sort(arr);可以将arr数组中的元素从小到大进行排序操作,然后使用输出操作可以将排序之后的数组逐个输出,此方法常常用于快速开发中,Arrays类还有一个toString方法可以直接将数组中的元素按照字符串的类型进行打印。
获取数组中最大元素:
public class MaxArray{
public static void main(String[] args){
int[] arr={2,3,4,9,2,4,6};
int max=getMax(arr);
System.out.println("max="+max);
}
public static int getMax(int[] arr){
int max=arr[0];
for(int i=0;i<arr.length;i++){
if(arr[i]>max){
max=arr[i];
}
}
return max;
}
}
7、选择排序:“选择排序”就是在数组中每个元素从前往后每一个元素和后面的“所有元素”进行大小比较,符合要求就进行换位操作。
public static void f(int[] arr){
for(int i=0;i<arr.length-1;i++){
for(int j=i+1;j<arr.length;j++){
if(arr[i]<arr[j]){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
}
8、冒泡排序:“冒泡排序”就是相邻的两个元素进行比较,如果前面的元素大于后面的元素,就进行换位操作,每次都是相邻的两个元素进行排序,直到最后没有元素为止。
public static void f(int[] arr){
for(int i=0;i<arr.length-1;i++){
for(int j=0;j<arr.length-i-1;j++){
if(arr[j]>arr[j+1]){
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
}
9、折半查找:
“折半查找”又称为二分查找,优点是比较的次数相对较少,查找的速度相对较快,平均性能较好。但是其缺点是待查找的表必须为有序表,且插入删除困难。因此折半查找方法是用于不经常变动而查找频繁的有序列表。首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字进行比较,如果两者相等,则查找成功。否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的元素,使查找成功,或直到子表不存在为止,此时查找不成功(其中关键的三个参数是mid、max、min参数,这三个参数至关重要)。
具体代码如下:
public static int f(int[] arr,int key){
int min,max,mid;
min=0;
max=arr.length-1;
mid=(min+max)/2;
while(arr[mid]!=key){
if(key>arr[mid]){
min=mid+1;
}
else if(key<arr[mid]){
max=mid-1;
}
if(min>max)
return -1;
mid=(max+min)/2;
}
return mid;
}
10、可变参数(针对数组):
通过一个例子来解释什么是可变数组。
public static void show(String s,int...arr){ //这里定义的arr就是可变参数的数组。
System.out.println(s);
for(int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
}
public static void main(String[] args){
show("NIHAO",1,2,3,4,5,6);
}
实际上,上面的三个“...”就是省略的可变数组的长度,这样可以方便的让自己随意输入自己想要的数组元素的个数。
注意:如果想要在方法中传递多个参数的话,最好将自己定义的这个“可变参数”的数组定义在参数列表的最后面,这样就不会报错。(比方:void f(String name,int i,int...arr){})
六、if()...else...和switch()语句
1、if语句格式:
if(条件){
执行的内容。
}
else{
不满足if中条件的话,将会执行的内容。
}
2、考题:
经常情况下会遇到“if条件之后只有一个执行语句”,那么为了简化代码,就将if(条件)后面的“{}”给省去了,但是有可能在面试的时候,考官会出这样一道题目:
if(x>1)
System.out.println("第一句话");
System.out.println("第二句话");
那么以上的结果将会是:只输出”第一句话“
3、switch语句:
在使用switch语句的时候,有一个大前提需要大家注意,那就是switch(x)语句中的x只接受四种类型的数据,分别是”byte“、”short“、”int“、”char“。所以如果自己的判断条件满足这个条件的话,可以使用switch语句,否则行不通!
switch(x)语句的基本格式:
int i=1,j=2;
char c='+';
switch(c){
case '+':
System.out.println(a+b);
break;
case '-':
System.out.println(a-b);
break;
default:
System.out.println("wrong");
break;
}
其中c是switch语句的条件,case分别是各种条件将会做出的相应的动作。上面的default是一个默认如果没有需要的条件将会出现的异常处理动作。
4、小总结:
从上面来看,if()...esle语句和switch语句有着惊人的相似之处。什么时候用什么方法呢?如果判断的具体数值不是太多的话,并且大前提是判断条件符合”byte、short、int、char这四种基本数据类型“的话,建议使用switch语句,从语句结构来看,层次分明,逻辑简单,效率高一点点,其它情况就使用if()...else语句吧。
七、循环总结
1、for循环格式如下:
for(初始化表达式;循环条件表达式;循环后的操作表达式){
执行的动作;
}
for循环的执行步骤是:初始化表达式只执行一次,接下来的是“循环条件表达式”,然后是“执行的动作”、“循环后的操作表达式”一直进行循环直到不满足条件为止。
2、for循环注意:
初始化并不一定非得是int x等于多少什么的,有可能System.out.println这样的语句,当自己程序的表达式比较多的情况下,每个分号中的语句用逗号隔开就可以。
3、for死循环:
for(;;){
执行的内容;
}
4、嵌套for循环:
for循环中嵌套一个for循环,外面的for循环控制着行数,内部for循环控制着列数,也就是说外面的for循环控制着循环一共有多少行,内部的for循环控制着每一行有多少个元素,这样嵌套for循环就可以实现有规律的遍历操作,比方说九九乘法口诀表。(注意的一点:for循环中的变量并不一定非得定义在其中,还可以直接定义在循环外面,这样就可以直接修改循环的变量条件,增强了灵活性)
使用嵌套for循环显示“九九乘法表”:
public class JiuJiuChengFaBiao {
public static void main(String[] args) {
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
System.out.print(i + "*" + j + "=" + (i * j) + "\t");
}
System.out.print("\n");
}
}
}
使用嵌套for循环实现“冒泡排序”:
import java.util.Arrays;
public class Maopaopaixu {
/**
* 冒泡排序的思想:比较相邻的两个元素的大小
* {3,1,7,0,5,8,12}
* 一次遍历即可
* {3,2,1}
* {2,3,1}
* {2,1,3}
* {1,2,3}
*/
public static void maopao(int[] arr){//要进行从小到大排列
for(int i=0;i<arr.length-1;i++){
for(int j=0;j<arr.length-i-1;j++){
if(arr[j]>arr[j+1]){
int temp=arr[j];//交换位置
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
}
public static void printout(int[] arr){
System.out.print("[");
for(int x=0;x<arr.length;x++){ //使用for循环遍历进行输出数组中的内容,这样很简单的
if(x==arr.length-1){
System.out.print(arr[x]);
}
else{
System.out.print(arr[x]+",");
}
}
System.out.print("]");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr=new int[]{3,1,7,0,5,8,12,6};
System.out.println("原数组是:");
printout(arr);
System.out.println();
System.out.println("经过冒泡排序的数组是:");
maopao(arr);
printout(arr);
}
}
使用嵌套for循环实现“选择排序”:
import java.util.Arrays;
public class XuanzepaixuTest {
/**
* {4,23,5,1,21,34}
* 使用选择排序进行操作然后输出排序前的内容和排序后的内容
* 什么是选择排序:从前往后每一个数和前后面的数值进行比较
* 5,4,3,2,1
* -----
* ----
* ---
* --
* -
*
*
*/
// 定义一个数组排序的功能
public static void f(int[] arr){
for(int i=0;i<arr.length-1;i++){//最后一个位置不用排序了
for(int j=i+1;j<arr.length;j++){//这个位置上的内容是随着i位置上的内容进行更改的
if(arr[i]<arr[j]){ //如果操作的是从大到小进行排列的话,我们可以将>改成<
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
}
//定义一个输出数组的功能
public static void printout(int[] arr){
System.out.print("[");
for(int x=0;x<arr.length;x++){ //使用for循环遍历进行输出数组中的内容,这样很简单的
if(x==arr.length-1){
System.out.print(arr[x]);
}
else{
System.out.print(arr[x]+",");
}
}
System.out.print("]");
System.out.println();//换行操作
// System.out.println(Arrays.toString(arr));//使用Array类输出数组的内容,很直接
}
//主函数调用这些功能
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr={4,23,5,1,21,34};
printout(arr);
f(arr);
printout(arr);
}
}
5、高级for循环:
for( 数据类型 变量名:被遍历的数组或者是集合 ){
要操作的内容
}
要求:遍历一个元素是int类型的arr数组。
int[] arr={1,2,3,4,5};
for(int i:arr){
System.out.println("i:"+i);
}
高级for循环遍历一String类型的Set集合:
Properties prop=new Properties();
prop.setProperty("zhangsan","43");
prop.setProperty("lisi","45");
Set<String> names=prop.stringPropertyNames();
for(String s : names){
System.out.println(s+":"+prop.getProperty(s));
}
6、高级for和一般for的区别:
(1)、对集合和数组进行遍历的时候,“高级for循环”只能对集合或者数组进行“获取”,但是不能进行更改操作。
(2)、“迭代器”除了遍历操作,至少还可以进行remove操作对集合中的元素进行修改动作。
(3)、如果是“ListIterator”的话,还可以在遍历过程中对集合进行增删查改呢!
(4)、“高级for循环”有局限性,因为必须有被遍历的目标,这点从“高级for循环”的格式就可以看出来!一般for循环可以不用目标数组或者集合就可以直接输出打印内容。比方说:
for(int i=0;i<100;i++){
System.out.println("i="+i);
}
7、总结:
(1)、凡是支持“迭代器”的集合都支持“高级for循环”!“高级for循环”的底层是“迭代器”!
(2)、在集合中,一定要定义集合的“泛型”!泛型用来存放集合中元素的类型,高级for循环在循环的时候需要元素的数据类型,所以一定要定义泛型!也就是定义集合中元素的数据类型,然后在使用高级for循环的时候,才可以正确使用!(这是必须的!)
8、while循环:
while(条件){
执行的动作;
}
9、while循环和if语句的差别:
一个是循环体,需要有结束的标志,一个是判断语句,不需要非得有结束的标志。所以如果while循环中的“条件”没有包含结束循环的意思,那么就需要在循环体中写出判断语句判定什么时候结束while循环。
10、for循环和while循环的区别:
(1)、变量有自己的作用域,对于for来讲,如果将用于控制循环的增量定义在for语句中,那么该变量只在for语句中有效,出去就没有作用了。for循环执行完毕之后,该变量在内存中被释放。
(2)、for和while可以进行互换的,如果需要定义循环增量的话,我觉得for循环会更加合适的。
11、什么时候使用循环结构:
当要对某些语句进行多次操作的时候,就使用循环结构。
12、do...while循环:
do{
执行动作;
}while(条件);
13、while和do...while区别:
while循环是先进行的判断,后进行的执行。do...while语句是先进行的执行动作,后进行的判断,所以我们可以得出结论:do...while循环至少执行一次里面的内容,而while循环必须满足条件之后才会执行所要进行的内容,所以如果判断同一个内容的话,最后的打印结果do...while语句有可能和while语句不相同,因为do...while循环“至少”执行一次!!!
14、break和continue的区别:
(1)、break语句应用范围:“选择”和“循环”结构,也就是说必须应用在循环结构或者是选择结构中。
(2)、continue语句应用范围:应用于“循环”结构,也就是说必须在循环结构中。
15、break和continue的意思:
(1)、break就是结束当前循环体,直接结束,跳出整个循环体,没有任何理由,下面的都不会执行到,当然这个循环体也就结束了。
(2)、continue就是继续的意思,continue下面的语句不会被执行到,强制循环体进行下次循环,提前结束了本次循环,但是循环仍在继续。
八、进制转换
1、十进制转二进制(摩2除2的过程):
用while循环来实现:
while(number>0){
System.out.print(number%2);
number=number/2;
}
十进制转二进制“查表法”:
public class BinarryToHex {
/**
* 十进制和二进制的转换用查表法来进行
*/
public static void f(int num){
char[] chs={'0','1'};//定义二进制的表
char[] arr=new char[32];//定义一个临时的变量表
int pos=arr.length;
while(num!=0){//这里的意思是将为0的去掉
int temp=num&1;
arr[--pos]=chs[temp];
num=num>>>1;//转换成二进制的时候移动的是1位!!!
}
for(int x=pos;x<arr.length;x++){
System.out.print(arr[x]);
}
}
public static void main(String[] args) {
System.out.println("please enter your code:");
Scanner reader=new Scanner(System.in);
int y=reader.nextInt();
f(y);
}
}
2、十进制转十六进制:
步骤:
(1)、先和15进行&操作,然后进行判断是否大于9。
(2)、然后进行移位操作,移动4位。
public static void toHex(int num) {
StringBuffer s = new StringBuffer();
for (int i = 0; i < 8; i++) {
int temp = num & 15;//进行与操作&
if (temp > 9)
s.append((char) (temp - 10 + 'A'));
else
s.append(temp);
num = num >>> 4;//移位操作,两步即可搞定
}
System.out.println(s.reverse());//反转操作
}
3、十进制转八进制
因为很少见,所以这里就不说了!
九、常用类
1、Math数学类常用方法总结:
(1)、Math.ceil(12.44); //返回大于指定数的最小整数,返回的数值是13。
(2)、Math.floor(12.44); //返回小于指定数的最大整数,返回的数值是12。
(3)、Math.round(12.4); //返回的是四舍五入的内容,结果是12。
(4)、Math.round(12.5); //返回的是四舍五入的内容,结果是13。
(5)、Math.pow(2,3); //计算的是2的3次方
(6)、Math.random(); //输出0到1的任意一个double类型的数据
(7)、Random r=new Random(); r.next(数值); //输出0到“数值”之间的任意一个“数”,输出的是整数,没有小数点,上面的“random”是double类型,有小数点,还有很多的小数。所以使用next()方法可以直接输出整数,方便快捷。
2、Calendar日期类:
(1)、概述
从jdk1.1开始,Data日期类正式被Calendar日期类替代。Calendar c=Calendar.getInstance();的意思是使用默认时区和语言环境获得一个日历,然后就可以使用类中自带的方法进行相对应的操作。
(2)、注意
实际的使用中,自己经常会遇到输出“月份”的时候,会自动的减少1,这是为什么呢?因为month是有数值限制的,也就是说只能从1到12这12个数字,但是老外规定,如果想要用数值输出月份的话,那么就是从下标0开始输出的,所以可以使用“查表法”自己定义自己想要的日期格式。
(3)、查表法
定义一个“数组”,里面存放自己事先定义好的内容,因为数组有"下标",“下标”是从0开始的,自己定义的元素是从“下标0”开始的,下边是一个程序小示例
public static void main(String[] args) {
Calendar c=Calendar.getInstance(); //使用默认时区和语言环境获得一个日历,返回的是一个Calendar类型的c参数。
String[] mounth01={"一月份","二月份","三月份","四月份","五月份","六月份","七月份","八月份","九月份","十月份","十一月份","十二月份",}; //自己定义的数组。
String[] weak01={"","星期日","星期一","星期二","星期三","星期四","星期五","星期六",}; //老外的星期天是从“日”开始的。
String[] hour01={"二十四点钟","一点钟","二点钟","三点钟","四点钟",
"五点钟","六点钟","七点钟","八点钟",
"九点钟","十点钟","十一点钟","十二点钟",
"十三点钟","十四点钟","十五点钟","十六点钟",
"十七点钟","十八点钟","十九点钟","二十点钟",
"二十一点钟","二十二点钟","二十三点钟"};
int year=c.get(Calendar.YEAR);
int mounth=c.get(Calendar.MONTH); //这里定义month的意思就是上面字符数组中的下标,下面的weak同样是。
int weak=c.get(Calendar.WEEK_OF_MONTH);
int hour=c.get(Calendar.HOUR_OF_DAY);
int minute=c.get(Calendar.MINUTE);
int second=c.get(Calendar.SECOND);
System.out.println("现在是:"+year+"年"+","+mounth01[mounth]+","+weak01[weak]+","+hour01[hour]+","+minute+"分"+","+second+"秒");
}
3、Data日期类:
(1)、概述
Data已经从1.0版本开始被Calendar日期类替代了,所以以后尽量使用Calendar日期类,不要使用Calendar日期类。
4、Runtime运行类:
(1)、概述
见名知意,Runtime是和“运行”有关的内容。该类并没有提供构造函数,说明不可以new对象,让我直接想到该类中的方法都是静态的。但是!发现该类中还有非静态的方法!说明该类肯定会提供了方法获取本类对象,并且该方法是静态的,并且返回值类型是本类类型。由以上的这个特点可以看到该类使用了“单例设计模式”来完成的。
(2)、应用
比方说,可以打开一个exe程序文件,一个系统。
Runtime r=Runtime.getRuntime(); //创建Runtime对象,自身调用getRuntime方法返回自身的对象。
Process p=r.exec("程序.exe"); //调用exec方法,返回一个进程,同时启动程序。
Thread.sleep(4000); //调用进程,睡上4秒钟。
p.destory(); //撤销进程。
5、System系统类:
(1)、概述:
经常用到的一个类就是“System”类,System类在java.lang包中可以找到,为了获取系统的一些属性,可以使用方法System.getPorperties();返回的是一个Properties类型的对象,然后调用该对象的方法,就可以获取到系统的一些属性。
(2)、扩展:
已经知道,Properties是Hashtable的一个子类,也就是Map集合的一个子类对象,所以可以通过map的方法取出该集合中的元素,因为集合中都是字符串,并且所以没有泛型的定义。
(3)、常用方法:
获取系统中的信息:.getProperty();
指定属性信息:.setProperty();
可以在jvm启动的时候,动态的加载一些系统的属性。
6、System类输出内容:
这句输出语句,查询api文档,里面有详细的System的介绍,其中比较重要的两个输入输出流是:
System.in
System.out
这两句话的标准输入输出设备分别是“键盘”和“控制台(显示器)”,但是如果不想从这两个标准的输入输出进行“读取”或者“写入”的话,该怎么办呢?
可以更改这个标准的输入输出配置:
System.setIn(InputSteam in);
System.setOut(PrintStream out);
这样就可以自定义输入与输出的方式,括号里面的内容查询api之后可以得知:里面定义的输入输出流。所以自己比方说定义一个从文本文件进行读入的“输入流”的话,将会是下面的示例:
System.setIn(new FileInputStream("d.txt"));
将会从一个名字叫做d.txt的文本文件中读取内容,然后输出到控制台中进行显示。(例子中演示的是一个文件的“字节流对象”)。