1. 变量/数据类型[1]
1.1. 基本数据类型
-
整数类型
- byte: 1个字节(8位),-128 ~ 127
- 二进制:最高位是符号位,0:正数;1:负数
- 公式: ~
- short:2个字节, ~
- int:4个字节, ~
- long:8个字节
- byte: 1个字节(8位),-128 ~ 127
-
小数(浮点类型)
- float:4个字节(32位)
- double:8个字节(64位)
- 能用float就不用double,省内存加速
-
布尔类型
- 表示真或假
-
字符类型
- char:单个字符(2个字节,可以存放汉字)
- 结论:在Java中,对char进行运算时,直接当作ascii码对应的整数对待
- String:字符串
- char:单个字符(2个字节,可以存放汉字)
1.2. 定义变量
- int a;这就定义了一个变量,变量名是a
- float b;这也定义了一个变量,表示一个float类型的小数,变量名是b
- 变量不能重复
1.3. 初始化变量
- 在定义变量时,就给值
- int a=45;这就是初始化变量a
1.4.变量赋值
- 先定义变量:int tt;再给值tt=780
1.5. 基本数据类型转换
- 自动转换
- 原则:数据只能从高精度到低精度转换:byte< short< int< long< float< double
- int a=1.2出错
- double b=3 可以
- 当一个整数和一个double运算时,运算结果会向高精度转
- 原则:数据只能从高精度到低精度转换:byte< short< int< long< float< double
- 小数默认是double,
- float a=3.4出错
- float a=3.4f 可以
- 强制转换:
- int a=(int)1.9:只取1
2. 运算符
2.1. 算术运算符
- 算术运算符
- *,/,+ ,-,
- %取模
- %运算可得两个数相除的余数
- += 左加;-= 左减
- /= 左除;%= 左取模
- Int a=90; a+=90; ==>a=a+90 输出180
- Float b=89.7f; b+=a; ==>b=b+a 输出 179.7
- ++ 自加; -- 自减
int a=56;
int b=a++;//b=a;a=a+1;
System.out.println(b);//输出56
System.out.println(a);//输出57
int a=56;
int b=++a;//a=a+1; b=a;
System.out.println(b);//输出57
System.out.println(a)=//输出57
2.2. 关系运算符
- == 等于;!= 不等于
-
; <; >=; <=
2.3. 逻辑运算符
- && 与;
- || 或;
- !非
3. 三大流程控制
- 顺序控制
- 分支控制
//1)单分支
if(条件表达式){
语句;
}
//2)双分支
if(条件表达式){
语句;
}else{
语句;
}
//3)多分支
if(条件表达式){
语句;
}else if(条件表达式){
语句;
}else if(条件表达式){
语句;
}else{
语句;
}//找到一个入口后,即使下面的条件符合,也不会再进入
b.switsch(条件表达式){
case 常量1:
语句1;
break;
case常量2:
语句2;
break;
...
case常量n:
语句n;
break;
default:
语句;
break;
}
//条件表达式数据类型,应和case后的常量类型一致
//Switch中可用的数据类型:byte,short,int,char,enum
- 循环控制
//for循环
for(循环初值; 循环条件; 步长){
语句; //循环体
}
//while循环
while(循环条件){
语句;//循环体
}
//do while循环
Do{
语句;//循环体
}while(条件);
4. 数组
一维数组
- 特点
- 数组可以存放多个同一类型的数据
- 对象数组在定义后,复制时需要再次为每个对象分配空间[new 对象]
- 数组大小必须事先指定
- 数组下标是从0开始编号
- 输出数组
int[] arr={1,3,6,8,10};
for(int i=0; i<arr.length; i++)
{
System.out.print(arr[i]);
}
- 用法
//1. 程序员用法
//数组的定义
int a[]=new int[5];//数据类型 数组名[] =new 数据类型[大小];
//数组的引用
a[2];//数组名[下标] 比如:使用a数组的第三个数
//2. 没事找事用法
//第一步:先声明数组
int[] a;//数据类型 数据名[]; 或 数据类型[] 数组名;
//第二步:创建数组
A=new int[5]//数组名=new 数据类型[大小];
//第三步:数组引用
a[2];
//3. 古板用法
//第一步:初始化数组
Int a={2,5,6,89,30};//数据类型 数组名[]={元素值, 元素值,...} 相当于:int a[]=new int[5]; a[0]=2;a[1]=5...
//第二步:数组的引用
a[2];
多维数组
5.排序,查找
比较字符串内容是否相等时, 用squals, 不要用==
排序是将一群数据,依照指定的顺序进行排列的过程
内部排序
将需要处理的所有数据都加载到内部存储器中进行排序
交换式排序法
运用数据值比较后,依照判断规则对数据位置进行交换
冒泡排序法(Bubble Sorting)
- 它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。
class Bubble{
//排序方法
public void sort(int arr[])
{
int temp=0;
//排序
//外层循环,决定走几趟
for(int i=0; i<arr.length-1; i++){
//内层循环,开始逐个比较, 如果发现前一个数大于后一个数,则交换
for(int j=0; j<arr.length-1-i;j+1)
{
if(arr[j]>arr[j+1])
{
//换位
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
}
}
快速排序法(Quicksort)
选择式排序法
选择排序法(Selection Sort)
//选择排序法(Selection Sort)
class Select1{
//排序方法
public void sort(int arr[])
{
int temp=0;
for(int i=0; i<arr.length-1; i++)
{
//假设第一个数最小
int min=arr[i];
//记录最小数的下标
int minIndex=i;
for(int j=i+1; j<arr.length; j++)
{
if(min>arr[j])
{
//修改最小
min=arr[j];
minIndex=j;
}
}
temp=arr[i];
arr[i]=arr[minIndex];
arr[minIndex]=temp;
}
}
}
class Select2{
public void sort(int arr[]){
int temp=0;
for(int i=0; i<arr.length-1; i++)
{
for(int j=i+1; j<arr.length; j++)
{
if(arr[i]>arr[j])//假设arr[i]最小
{
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
}
}
堆排序法(Heap Sort)
插入排序法
属于内部排序法,是对与欲排序的元素以插入的方式找寻该元素的适当位置,已达到排序的目的
插入排序法(Insertion Sort)
- 把n个待排序的元素看成一个有序表和一个无序表。开始时有序表中只包含一个元素,无序表中包含(n-1)个元素。排序过程中,每次从无序表中去除第一个元素,把它的排序码依次与有序表元素的排序码进行比较,将它插入到有序表中的适当位置,使之成为新的有序表
//插入排序法
class Insertion{
//排序方法
public void sort(int[] arr)
{
for(int i=1; i<arr.length; i++)
{
int insertVal=arr[i];
int index=i-1;
//insertVal准备和前一个数比较
while(index>=0&&insertVal<arr[index])
{
//将arr[index]向后移
arr[index+1]=arr[index];
//index继续向前走
index--;
}
arr[index+1]=insertVal;
}
}
}
谢尔排序法(Shell Sort)
- 先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的),分别进行直接插入排序。待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。
二叉树排序法(Binary-tree Sort)
- 处理过程:先将第一个元素作为有序序列,进行n-1次插入。用二分查找的方法查找待排元素的插入位置,将待排元素插入。
6.2 外部排序###
数据量过大,无法全部加载到内存中,需要借助外部存储进行排序
合并排序法
- 将已排好序的A、B合并成E,C、D合并成F,且E、F内部数据均已排好序。再将已排好序的E、F合并成G, 且G的内部数据已排好序。至此,四个文件A、B、C、D完成排序。
直接合并排序法
6.3 查找
- 顺序查找[较简单]
- 二分查找[演示]
package com.one_dimensional_array;
public class Demo5_3 {
public static void main(String[] args) {
int arr[]= {2,5,7,12,25};
BinaryFind bf=new BinaryFind();
bf.find(0, arr.length-1, 12, arr);
}
}
//二分
class BinaryFind{
public void find(int leftIndex,int rightIndex, int val, int[] arr)
{
//首先找中间的数
int midIndex=(rightIndex+leftIndex)/2;
int midVal=arr[midIndex];
if(rightIndex>=leftIndex) {
//如果要找的数比midVal小
if(midVal>val)
{
//在arr左边数中找
find(leftIndex, midIndex-1, val, arr);
}else if(midVal<val)
{
//在arr的右边数中找
find(midIndex+1, rightIndex,val,arr);
}else if(midVal==val)
{
System.out.println("找到下标"+midIndex);
}
}
}
}
7. 集合框架
7.1 集合类
- 较常用:
- HashMap, HashSet, Hashtable(Legacy), ArrayList, LinkedList, Vector(Legacy), Stack(Legacy)
- 分类
- List结构的集合类
- Arraylist类,LinkedList类,Vector类,Stack类
- Map结构的集合类
- HashMap类,Hashtable类
- Set结构的集合类
- HashSet类,TreeSet类
- Queue结构的集合
-Queue接口
- List结构的集合类
7.2 常用方法
- ArrayList
package com.one_dimensional_array;
import java.util.*;
public class Demo_Test {
public static void main(String[] args) {
ArrayList a1=new ArrayList();
int a=0;
int b=1;
int c=2;
//添加
a1.add(a);
a1.add(b);
a1.add(c);
System.out.println(a1);
//删除
a1.remove(a);
System.out.println("====删除a====");
//遍历找到
for(int i=0;i<a1.size();i++)
{
System.out.println(a1.get(i));
}
}
}
/*结果:
[0, 1, 2]
====删除a====
1
2*/
- LinkedList
public static void main(String[] args) {
LinkedList l1=new LinkedList();
Emp emp1=new Emp("sa01","aa",1.2f);
Emp emp2=new Emp("sa02","bb",1.2f);
//把emp1加在链表的最后面,emp1加在最前
l1.addLast(emp1);
l1.addFirst(emp2);
for(int i=0;i<l1.size();i++)
{
System.out.println(((Emp)l1.get(i)).getName());
}
}
class Emp{
...//假设已写好( ̄▽ ̄)"
}
- Vector
public static void main(String[] args) {
Vector vv=new Vector();
vv.add(emp1);
for(int i=0;i<vv.size();i++)
{
Emp emp=(Emp)vv.get(i);
}
}
class Emp{
...//假设已写好( ̄▽ ̄)"
}
- Stack
- HashMap
public static void main(String[] args) {
Emp emp1=new Emp("sa01","aa",1.2f);//编号,姓名,工资
Emp emp2=new Emp("sa02","bb",1.2f);
Emp emp3=new Emp("sa03","cc",1.2f);
//创建一个HashMap对象
HashMap hm=new HashMap();
//将emp放入hm
hm.put("sa01",emp1);
hm.put("sa02", emp2);
//hm.put("sa02",emp3);//emp3自动覆盖原先的key"sa02"中的value
hm.put("sa03", emp3);
//如果你要查找编号是sa01
if(hm.containsKey("sa02"))
{
System.out.println("有该员工");
//如何取出,键k<-->值v
Emp emp=(Emp)hm.get("sa02");
System.out.println("名字:"+emp.getName());
}
else
{
System.out.println("查无此人");
}
//遍历HashMap中所有的key和value
//Iterator迭代
Iterator it=hm.keySet().iterator();
//hasNext返回一个boolean
while(it.hasNext())
{
//取出key
String key=it.next().toString();
//通过key取出value
Emp emp=(Emp)hm.get(key);
System.out.println("名字"+emp.getName());
System.out.println("工资"+emp.getSal());
}
}
class Emp{
...//假设已写好( ̄▽ ̄)"
}
7.3 比较
-
ArrayList和Vector的区别
- 同步性:
- Vector是同步的。这个类中的一些方法保证了Vextor中的对象是线程安全的。
- ArrayList是异步的。因此ArrayList中的对象并不是线程安全的。因为同步的要求会影响执行的效率,所以如果你不需要线程安全的集合,那么使用ArrayList可以避免由于同步带来的不必要的性能开销
- 数据增长:
- 从内部实现机制来讲,ArrayList和Vector都是使用数组(Array)来控制集合中的对象。当你向这两种类型中增加元素的时候,如果元素的数目超出了内部数组目前的长度,它们都需要扩展内部数组的长度。
- Vector缺省情况下自动增长原来一倍的数组长度,ArrayList是原来的50%
- 所以如果你要在集合中保存大量的数据,那么使用Vector较好,因为你可以通过设置集合的初始化大小来避免不必要的资源开销
- 同步性:
-
HashMap和Hashtable的区别
-
历史原因:
- Hashtable是基于陈旧的Dictionary类的
- HashMap是Java 1.2引进的Map接口的一个实现
-
同步性:
- Hashtable是同步的。这个类中的一些方法保证了Hashtable中的对象是线程安全的
- HashMap是异步的。因此HashMap中的对象并不是线程安全的。因为同步的要求会影响执行的效率,所以如果你不需要线程安全的集合,那么使用HashMap是一个很好的选择
-
值:
- Hashtable不能放入空值(null)
- HashMap可以让你将空值作为一个表的条目的key或value
-
7.4 总结
- 如果要求线程安全:使用Vector、Hashtable
- 如果不要求线程安全:使用ArrayList、LinkedList、HashMap
- 如果要求键值对:使用HashMap、Hashtable
- 如果数据量很大:使用Vector
8. 泛型
-
基本概念
-
泛型本质:参数化类型,即所操作的数据类型被指定位一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法
-
好处:
- 类型安全:在没有泛型的情况下,通过对类型Object的引用来实现参数的“任意化”。“任意化”的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器不提示错误,在运行的时候才出现异常,这就是个安全隐患。
- 向后兼容
- 层次清晰
- 性能较高:用GJ编写的代码可以为java编译器和虚拟机带来更多的类型信息。这些信息对java程序做进一步优化提高条件
-
- 反射机制
- 通过反射机制,我们可以得到某一类型的很多信息(比如得到成员函数名)
9. 异常
-
基本概念
- 当出现程序无法控制的外部环境问题(用户提供的文件不存在、文件内容损坏、网络不可用...)时 ,Java就会用异常对象来描述
-
异常分类
- 检查性异常:java.lang.Exception
- 程序正常,但因为外在的环境条件不满足而引发
- 运行期异常:java.lang.RuntimeException
- 意味着程序存在bug,如数组越界、0被除、入参不满足规范... 这类异常需要更改程序来避免,java编译器强制要求处理这类异常
- 错误:java.lang.Error
- 少见,也很难通过程序解决。他可能源于程序的bug。但一般更可能源于环境问题,如内存耗尽。错误在程序中无需处理,而由运行环境处理
- 检查性异常:java.lang.Exception
import java.io.*;
import java.net.*;
public class Demo9_1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//检查异常1.打开文件
FileReader fr=new FileReader("d:\\aa.text");
//2.连接一个192.168.12.12 ip的端口号4567
Socket s=new Socket("192.168.12.12",78);
//运行异常1. 0被除
int a=4/0;
//2.数组越界
int arr[]= {1,2,3};
System.out.println(arr[234]);
}
}
-
异常处理
-
在发生异常的地方直接处理;
-
try...catch
程序运行异常时,将从异常发生点中断程序并向外抛出异常信息 -
finally
如果把finally块置于try...catch语句后,finally块一般都会得到执行。它相当于一个万能的保险。即使前面的try块发生异常,而又没有对应异常的catch块,finally块将马上执行 - 以下情形,finally块将不会被执行
- finally块中发生了异常
- 程序所在线程死亡
- 在前面的代码中用了
System.exit();
- 关闭CPU
-
-
将异常抛给调用者,然调用者处理
throws
-
//直接处理
package com.one_dimensional_array;
import java.io.*;
public class Demo9_1 {
public static void main(String[] args) {
//检查异常1.打开文件
FileReader fr=null;
try {
System.out.println("go on");
fr=new FileReader("d:\\aa.txt");
}catch(Exception e) {
//把异常的信息输出,利于排错
System.out.println("111");
e.printStackTrace();
//System.exit(-1);finally将无机会执行
//处理
}finally{
System.out.println("进入finally");
//这个语句块,不管有没有异常,都会被执行
//把需要关闭的资源,如[文件、链接、内存...]
if(fr!=null)
{
try {
fr.close();
}catch(Exception e) {
e.printStackTrace();
}
}
System.out.println("aa");
}
//抛出异常
package com.one_dimensional_array;
import java.io.*;
public class Demo9_2 {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
Father father=new Father();
father.test1();
}
}
class Father{
private Son son=null;
public Father() {
son=new Son();
}
public void test1() throws Exception {
System.out.println("1");
son.test2();
/* try {
son.test2();
}catch(Exception e) {
System.out.println("父亲");
e.printStackTrace();
}*/
}
}
class Son{
public void test2() throws Exception{
FileReader fr=null;
fr=new FileReader("d:\\aa.txt");
}
}
-
持续更新中~笔记记录自韩顺平Java网课 ↩
网友评论