程序员学习资源站
数据类型和变量
数据在计算机内部都是二进制的形式表示的,为方便操作高级语言引入了数据类型和变量的概念。
数据类型是对数据的归类,以便于理解和操作,Java中有四种基本类型:
为了操作数据,需要吧数据存放在内存,所谓内存在程序看来就是一块有地址的连续空间,数据放到内存中某一位置,为了方便操作,就会给该位置起一个名字,编程语言通过变量来描述这一过程。
赋值
定义了变量和就确定了一块内存空间,但该空间的值是不确定的,就需要给该空间制定一个明确的值
基本类型
需要注意的是:
数组类型
需要注意的是:
int[] arrA = {1,2,3} int[] arrB = {1,2,3,4} arrA = arrB
以上代码说明了为什么数组需要存两块内存空间,数组A的长度是3,数组B的长度是4,如果直接将B的内容赋值给A的话A没有足够了 空间存放下B,如果换成两块控件的话,只需要交换内容控件的地址,不需要去改变内容的位置。
基本运算
有了值之后,便可以对数据进行运算。
主要包含:
需要注意的有:
b = a++-1 => b = a - 1 ,a = a + 1 c = ++a-1 => a = a + 1 ,c = a - 1
条件执行
没有了条件执行那么我们的程序都是由上而下执行的
if
使用if我们可以进行一些判断,当满足特定的条件时紧跟if的代码块将会执行
int a = 4; if(a % 2 ==0){ System.out.print("in") } //if(a % 2 == 0) System.out.print("in"); 与上面效果相同 //不带{}的情况会默认执行后面的第一条语句,应该避免使用这种形式
if/else
使用if/else的语法可以让我们在不满足条件的情况下指定执行的语句
int a = 4; if(a % 2 ==0){ System.out.print("in") }else{ System.out.print("else in") //不满足则执行 }
if/else if/else
该语法让我们可以定义多个条件与上面相同,区别在于可以定义多个满足的条件
int a = 4; if(a % 2 ==0){ System.out.print("double in") }else if(a % 3 == 0){ System.out.print("single in") }else{ System.out.print("else in") //不满足则执行 }
三元运算符
三元运算符是一种特殊的语法,类似于if/else
int a = 4; a % 2 == 0 ? System.out.print("in") : System.out.print("else in") //参考if/else
switch
switch可以通过不同的值来选择执行不同的分支
需要注意每个case后记得break不然会执行多个分支
switch (i){ case 1: System.out.println(1); break; case 2: System.out.println(2); break; case 10: System.out.println(10); break; default: System.out.println("lol"); } //i是10的话输出10 1,2,10意外的数字输出lol
switch中的表达式的值可以是 补充:包括以下的包装类型
实现原理
程序最终都是一条一条执行的指令,这些指令会修改指令指示器的值,让cpu跳到一个指定的地方执行
有条件跳转和无条件跳转,条件跳转是检查某个条件满足则跳转,无条件跳转则是直接进行跳转
switch的转换可能不一样,当分支少的情况下可能会转化为跳转指令,如果分支比较多,是同条件跳转的效率就会低,可能会使用跳转表这种效率高的方式
条件值 | 跳轉地址 | 条件值 | 跳轉地址 |
---|---|---|---|
值1 | 代码块地址1 | 值2 | 代码块地址2 |
值3 | 代码块地址3 | 值4 | 代码块地址4 |
效率高的原因是其中的值必须为整数且按大小顺序排序,这样就可以使用二分法来查找,如果值是连续的还会特殊化处理,转化为一组连续的数组,这样值就为数组的下标代码块地址就为内容。
case的值不要求按顺序排列程序会自动进行排列
循环
循环可以使我们重复的执行某一代码块,以达到统计等目的
循环主要有
for(int i = 0;i<=10;i++){ System.out.println(i); } //会打印 0 - 10
除了中间的条件必须存在外变量定义和自增都可以在其他地方完成,但是必须写分号
int i = 0; for(;i<=10;){ System.out.println(i); i++; }
都为空那么就是一个死循环
for(;;){ System.out.println(i); }
while
while会先进行条件判定,如果条件为true则进行循环,false则不进行循环
int i = 0; while(i <= 100){ System.out.println(i); i++; }
do/while
do/while会先执行代码块然后再进行判断和循环
int i = 1; do { System.out.println(i); i++; } while (i <= 100);
for each
for each 是普通for循环的加强版,如果不需要使用索引的情况下就可以使用for each
int[] arr = {1,2,3,4}; for(int j : arr){ System.out.println(j); }
另外 两个关键字
函数(一)
一些可以重复调用的功能,将功能代码封装在函数中,就只需要在多个地方调用该函数即可,可减少冗余代码
函数的主要组成部分
常见的函数有main函数,该函数比较特殊是程序的入口,运行时会先找到main函数然后逐行执行。
/** * 模版方法设计模式 * @author 李幸 * @date 2018/3/20 * @time 23:10 */ public class TemplateMethod { public static void main(String[] args) { Template template = new SubTemplate(); template.spendTime(); } }
参数
函数中的参数可以是变量,常量,运算表达式,也可以是其他函数执行返回的结果
值传递
说道参数,就要提到java中参数的传递方式,java中的传递方式都是值传递的所以外部传入的变量在函数内部做改变时不会影响外部变量的值,但是如果是传递对象的话那么就会改变对象中的值,因为传递对象的时候实际传递的是对象的引用,就导致函数内部的变量与函数外部的变量引用了同一份内容,所以外部对象中的值会被修改。
在jdk1.5之后java支持可变长参数
public class Test { public static void main(String[] args) { Test test = new Test(); test.sum(1,23,3,4,5); } public void sum(int ... nums){ int sum = 0; for(int i : nums){ sum += i; } System.out.println(sum); } }
如果传入的值类型一致且需要多个不确定的情况下就可以用这种形式来定义,就免去了写多个重载方法了,需要注意的是可变长参数必须在参数列表的最后才可以。
函数的返回
在函数内部如果想要在一定条件退出该函数或者想要返回结果可以使用return
public class Test { public static void main(String[] args) { Test test = new Test(); int sum = test.sum(1,23,3,4,5); } public int sum(int ... nums){ int sum = 0; for(int i : nums){ sum += i; } return sum; } }
如果不想返回值只想终止函数那么方法返回值的修饰必须为void
函数的重载
同一个类中如果函数名相同,函数的参数列表不同,函数参数个数相同但是类型不同的情况下就构成了函数的重载
public class Test { public static void main(String[] args) { Test test = new Test(); int sum = test.sum(1,23,3,4,5); } public int sum(String str,int ... nums){ int sum = 0; for(int i : nums){ sum += i; } return sum; } public int sum(int min,int ... nums){ int sum = 0; for(int i : nums){ sum += i; } return sum; } }
两个sum函数重载了
在调用函数的过程中,对于参数也会自动进行类型转化以适配适合的函数来进行调用
递归
一个函数调用它本身就形成了递归,注意递归必须有终止状态否则会一直执行下去
public class Test { public static void main(String[] args) { Test test = new Test(); System.out.println(test.factorial(3)); } public int factorial(int n){ if(n == 0){ //这边定义了终止的状态 return 1; }else{ return n * factorial(n-1); } } }
栈
栈是一块内存,但它的使用有特殊的约定,一般是先进后出的,往其中存放数据称为入栈,取出数据称为出栈,
最下面为栈底最上面为栈顶,栈一般从高位地址向低位地址扩展,栈底的地址是最高的相反栈顶是最低的
计算机系统主要使用栈来存放函数调用过程中需要的数据,参数,反回的地址以及函数中定义的局部变量。在函数被调用时这些内存被分配,在调用结束时这些内存就被释放了
返回值不太一样,它可能在栈中存放这些数据,有的系统使用系统内的存储器存储返回值
栈的空间是有限的函数每一次的调用,其参数,局部变量,返回地址等都会占用栈的控件,所以如果当递归调用时如果递归的深度过于深的情况下就会出现 java.lang.StackOverFlowError ,栈空间溢出。
堆
对于数组和对象类型通常用两块内存去存储,一块存放实际的内容,一块存放内容的地址。实际内容(对象等)是在堆上创建的。在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。
例如定义
public class Test { public static void main(String[] args) { Car car = new Car(); } } class Car{ String name; Double price; }
执行这段代码,main方法压栈,在栈中先会存在main方法的参数 args
Car car = new Car();
new Car() 返回的这个对象会在堆中开辟一片空间,会将返回的地址给car这个引用。
car这个引用则保存在栈中
如图:
整数的二进制表示及加减运算
正整数的二进制
我们最熟悉的是十进制,例如 131,它实际的含义其实是 1 x 10^2 + 3 x 10^1 + 1 x 10^0
从右到左每个位置都有一个位权,从1开始
在十进制中每个位置都能有0-9中的十个里的一个 来表示,但是在二进制中只有0或者1两个数,位权从右到左依次为1,2,4,8等
例如 2 的二进制为 10 ,10 的二进制为1010
负整数的二进制
负数的二进制表示就是其对应正数的补码表示
整数有四种类型 , byte,short,int,long 分别占 1,2,4,8个字节,分别占8,16,32,64位
在二进制中最高位表示符号位, 0 表示正数,1 表示负数
例如 byte i = -10; 对应二进制应该为 11110110,第一反映即然符号位为1那么为什么不是10001010呢?
这就涉及到了计算机中的三种表示法,三种表示方法均有符号位和数值位两部分
下面以byte i = -10 举例
计算机只能进行 + 运算 计算 1- 1 的时候实际是 1+ (-1),在计算机系统中,数值一律用补码来表示和存储。
例如 1-1 实际是 1 + (-1)
1 -> 00000001
+
-1 -> 11111111
= 000000000
进位与十进制数类似但是是逢2进一位
展开 +
收起 -
Copyright 2018-2019 XZ577.com 码农之家 版权所有 苏ICP备18032832号
声明:本站所有资源都来自互联网 如有异议 请与本站联系