Java 基础篇

数据类型

基本数据类型

由于java是强类型语言,所以要进行有些运算的时候,需要用到类型转换。

低-----------------------------高
byte,short,char-->int-->long-->float-->double

强制类型转换 (类型)变量名 高—>低

自动转换 低—>高

注意点:

  • 不能对布尔类型进行转换;
  • 不能把对象类型转换为不相干的类型;
  • 在把大容量转换到低容量的时候,强制转换
  • 转换的时候可能存在内存溢出,或者精度问题
System.out.println((int)23.7); //23
System.out.println((int)-45.89f); //-45
char c = 'a';
int d = c+1;
System.out.println(d);  //98

操作比较大的数的时候,注意溢出问题

JDK7新特性,数字之间可以用下划线分割

int money = 10_0000-0000;

变量

变量就是可以变化的量叫变量。

变量的作用域

  • 类变量(归属类)
  • 实例变量(归属于对象,不自行初始化,有默认值)
  • 局部变量(归属于方法:必须声明和初始化值)
public class Variable{
    static int a = 0; //类变量
    String str = "Hello World"; //实例变量
    public void method(){
        int i = 0; //局部变量
    }
}

常量

常量(Constant):初始化(initialize)后不能再改变值!不会变动的值。(它的值被设定后,在程序运行过程中不允许被改变)

final 常量名 = 值;
final double PI = 3.14;

常量名一般使用大写得字符。

逻辑运算

&& (与)、||(或)、!(非,取反)

&&:左右两边都为真,结果才为true;(有短路效应,第一个为false就不向下进行判断)

||:两个结果有一个为真,结果便为true;(有短路效应,第一个为true就不向下进行判断)

!( ):如果是真,则变为假;如果是假,则变为真。

位运算

A = 0011 1100
B = 0000 1101 
A&B = 0000 1100 //(按位比较相同返回值,不同返回0)
A|B = 0011 1101 //(都是0则为0,都是1则为1,如果有一个1,直接为1)
A^B = 0011 0001 //(如果相同就位0,否则就位1)
~B = 1111 0010  //(取反)

左移 << *2 ;

右移 >> /2。

JavaDoc命令

通过cmd窗口javadoc 参数 Java文件 生成自己的API文档

Java流程控制

Scanner控制台输入

接收键盘输入

Scanner scanner = new Scanner(System.in);

//凡是属于IO流的类必须关闭资源,如果不关闭会一直占用资源。

通过Scanner类的next()与nextLine()方法获取输入的字符串,在读取前我们一般需要使用hasNext()与hasNextLine()判断是否还有输入的数据。

循环语句打印三角形

方法

实参、形参

public static void main(String [] args){
    int sum = add(1,2); //实际参数:实际调用传递给他的参数
}

//方法(小括号内的是形式参数,用来定义作用的)
public static int add(int a,int b){
    return a+b;
}

可变参数

数组

数组的四个基本特点

  • 其长度是固定的,数组一旦配创建,它的大小就是不可以改变的;
  • 其元素必须是相同类型,不允许出现混合类型;
  • 数组中的元素可以是任何数据类型,包括基本数据类型和引用类型。
  • 数组变量属于引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量;
  • 数组本身就是对象,java中对象实在堆中的,因此数组无论保存原始类型还是其它对象类型,数组对象本身实在堆中的。

二维数组

二维数组内的元素是数组

冒泡排序

冒泡排序,两层循环,外层冒泡轮数,里层一次比较

比较数组中,两个相邻的元素,如果第一个数比第二个数大,我们就交换他们的位置,每一次比较都会产生一个最大的,或者最小的数字,下一轮则可以少一次排序,依次循环,知道结束。

int temp = 0;
for(int i = 0;i<array.length-1;i++){
    for(int j=0;j<array.length-1-i;j++){
        if(array[j]>array[j+1]){
            temp = array[j+1];
            array[j+1]= array[j];
            array[j] = temp;
        }
    }
}

面向对象

面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据。

面向对象的三大特性:

  • 封装
  • 继承
  • 多态

继承

super 和 this:

  1. super 调用父类的构造方法,必须写在子类中构造方法的首行
  2. super 必须只能出现在子类的方法或者构造方法中
  3. super 和 this 不能同时调用构造方法

this:

代表的对象不同:

​ this:本身调用者这个对象

​ super:代表父类对象的应用

前提:

​ this:没有继承也可以使用

​ super:只能在继承条件下才可以使用

构造方法

​ this( ):本类的构造方法

​ spuer( ):父类中的构造方法

重写:需要有继承关系,子类重写父类的方法!(都相同)

  1. 方法名必须相同
  2. 参数列表参数必须相同
  3. 修饰符子类权限必须大于父类
  4. 抛出的异常:范围,可以被缩小,但不能扩大

多态

动态编译、类型、可扩展性

同一方法可以根据发送对象的不同而采用多种不同的行为方式(同一个接口,使用不同的实例而执行不同的操作)。

多态存在的条件:

  • 有继承关系
  • 子类重写父类方法
  • 父类引用指向子类对象

多态是方法的多态,属性没有多态

注意:

static 修饰的方法不能被重写,static 修饰的方法属于类

final 修饰的方不能被重写

private 修饰的方法不能被重写

static关键字

static 修饰:属性、方法、代码块

  • static 方法:归属于类,可以 (类名.方法 )调用

  • static 代码块:在构造方法前执行而且只执行一次。

静态的只能访问静态的,不能访问非静态的(如果静态的访问非静态的需要先创建对象);

非静态的可以访问静态的;

静态方法和非静态方法的区别:

​ 静态方法:方法的调用只和左边定义的数据类型有关

//父类的引用指向子类
B b = new A();
b.test();// B的方法(父类的方法)

​ 非静态方法:子类重写父类的方法后执行子类,如果子类没有重写则还是执行父类的方法。

抽象类

abstract 可以修饰类,方法;

abstract 关键字修饰的类为抽象类:

  • 不能new 这个抽象类(不能创建对象),只能靠子类去实现它,约束它!
  • 抽象类的所有方法,继承了的其子类必须重写其抽象方法,或者子类声明为抽象类;
  • 抽象类中可写普通的方法;
  • 抽象方法必须卸载抽象类中。

abstract 修饰的方法为抽象方法:

​ 只有方法的名字,没有方法的实现,不用写大括号,直接分号结尾即可。

接口

接口 用 interface 关键字定义

  • 普通类:只有具体实现
  • 抽象类:具体实现的规范(抽象方法)都有!
  • 接口:只有规范!自己无法写方法-专业的约束!约束和实现分离:面向接口编程!

接口的作用:

  1. 约束;
  2. 定义一些方法,让不同的类实现
  3. 接口中的所有定义的方法其实都是抽象的 public abstract;
  4. 定义的常量 public static final;
  5. 接口不能被实例化,接口中没有构造方法;
  6. 可以实现多个接口用 implements 关键字;
  7. 实现了接口的类,就需要实现接口中的方法

内部类

异常

假如要捕获多个异常:从小到大捕获!

throw 主动抛出异常,一般在方法中使用

public void test(int a,int b){
    if(b==0){
        throw new ArithmeticException();//主动抛出异常
    }
    System.out.println(a/b);
}

throws 假设在方法中,处理不了这个异常,在方法上抛出

public void test(int a,int b) throws ArithmeticException{
    if(b==0){
    }
    System.out.println(a/b);
}

Throw 和 Throws 的区别:

​ 共同点:两者在抛出异常时,抛出异常的方法并不负责处理,顾名思义,只管抛出,由调用者负责处理。

​ 区别:

  1. throws 用于方法头,表示的只是异常的申明,而throw用于方法内部,抛出的是异常对象
  2. throws 可以一次性抛出多个异常,而throw只能一个;
  3. throws 抛出异常时,它的上级(调用者)也要申明抛出异常或者捕获,不然编译报错,而 throw 可以不申明或不捕获(这是非常不负责任的方式)但是编译器不会报错。

集合容器

为什么要使用集合而不是数组

集合和数组的相似点:

  • 都可储存多个对象,对外作为一个整体存在

数组的缺点:

  • 长度必须子初始化时指定,且固定不变
  • 数组采用连续存储空间,删除和添加效率低下
  • 数组无法直接保存映射关系(例:根据学号找到学生的名字)
  • 数组缺乏封装,操作繁琐

集合框架

  • List 接口存储一组不唯一,有序(索引顺序)的对象;
  • Set 接口存储一组唯一,无序的对象;
  • Map 接口储存一组键值对对象,提供key->value的映射
    • key 唯一无序
    • value 不唯一无序

List

list

  • 特点:有序(先后顺序,索引的顺序)、不唯一(可重复)

ArrayList 线性表中的顺序表:

  • 在内存中分配连续的空间,实现了长度可变的数组;
  • 优点:遍历元素和随机访问元素的效率比较高;(随机访问公式:**(起始地址+每个元素的长度*索引=最终地址)**
  • 缺点:添加和删除需大量移动元素效率低,按照内容查询效率低;

注意:ArrayList 按照**索引**查询元素快,如果按照需求查则慢;

LinkedList 线性表中双向链表:

双向链表储存结构图第一个hander为头指针,不保存数据,每保存一个元素的同时保存了该元素的下一个元素地址和前一个元素的地址;

  • 采用双向链表存储方式。
  • 缺点:遍历和随机访问元素效率低下
  • 优点:插入、删除元素效率比较高(但是前提也是必须先低效率查询才可。如果插入删除发生在头尾可以减少查询次数)

总结分析:

/**
 * 功能: 存储多个分数
 * 技能:ArrayList的使用
 * 
 * 分析:
 *  多个分数: 集合
 *  分数不唯一(可以相同),有顺序(先后顺序):List
 * 
    遍历Arraylist集合的三种方法:
     1.for
     2.foreach
     3.iterator迭代器
 * 注意:
 * 1.集合中只能放对象,不能放基本数据类型;(基本数据类型可以使用包装类放入,自动装箱)
 *  数组中即可以放对象,也能放基本数据类型;
 * 2.ArrayList:不唯一、有序(索引的顺序)
 * 3.ArrayList:常用的方法
 * list.add(19);         //add方法将元素添加到集合的末尾;
 * list.add(3, 88);      //将元素添加到指定位置,底层发生了大量的元素向后移动,效率低
 * list.addAll(list2);   //将多个数据添加到集合的最后
 * list.addAll(0,list2); //根据索引将多个元素添加到最前面
 * 
 * list.size();     //元素的个数;
 * list.get(i);     //获取第i个元素
 * list.iterator(); //将数据交给迭代器遍历
 
 * list.set(1,78);      //根据索引修改
 * list.remove(3);      //根据索引删除数据
   list.remove(new Integer(78)); //根据内容删除
   list.toArray();      //集合转数组
 * 缺点:
 *  1.繁琐:遍历取出元素时需要强制转换,否则是Object类型
 *   int object = (int)list.get(i)
 *  2.不安全:添加元素的时候可以加入不同的数据类型
 *   list.add("abc"); 
 * 解决:使用泛型
 * 泛型的好处
 *  1.简单
 *  2.安全 
 * @author Administrator
 *
 */
* 功能: 存储多个分数
 * 技能:LinkedList的使用
 * 
 * 不变的是什么
 *  1.运行结果不变
 *  2.代码相同
 *  
 * 变化的是什么
 *  1.底层结构不同
 *   ArrayList:连续的空间 数组
 *   LinkedList:不连续的空间 双向链表
 *   
 *  2.操作的过程不同
 *   list.add(3, 88); 
 *   ArrayList:大量的后移元素,效率低下
 *   LinkedList:创建新的节点储存88,并修改前后两个节点的指针,加入到第三个位置  效率比较高
 *  
 *  到底该使用ArrayList还是LinkedList
 *   1.随机访问频率高,建议使用ArrayList
 *   2.添加、删除操作比较多,建议使用LinkedList
 * 
 * LinkedList 增加了对首尾节点的操作
 * 

set

特点:无序、唯一(不重复)

  • HashSet

    • 采用Hashtable 哈希表存储结构(神奇的结构)
    • 优点:添加速度快 查询速度快、删除速度快;
    • 缺点:无序;
  • LinkedHashSet

    • 采用哈希表存储结构,同时使用链表维护次序;
    • 有序(添加顺序);
  • TreeSet

    • 采用二叉树(红黑树)的储存结构;

    • 优点:有序、查询速度比List快(按照内容查询);

    • 缺点:查询速度没有HashSet快;

按照内容查询速度的快慢:

哈希表–>树—>线性表 (由快到慢)

二叉树:

哈希表:

哈希表的主结构:

不是基于内容比较的,而是基于计算的,可以直接计算到存储的地址并访问;

例:

* 使用Set来存储过程
 * 
 * HashSet 底层结构是哈希表 速度快 无序 唯一
 * LinkedHashSet 底层结构是哈希表+链表 有序的(存储顺序)唯一
 * TreeSet 底层结构是红黑树(二叉树、二叉排序树、二叉平衡树)速度比较快,介于线性表和哈希表之间
 *          有序(自然顺序 大小顺序) 唯一
 * 
 * set的遍历
 *  1.for-each
 *  2.Iterator
 *  3.不能使用for循环,因为没有get(i)
 *  
 *  set相比Collection并没有增加方法
 *  但是List相比Collection增加了一些和索引相关的的方法
 *  add(i,elem);
 *  remove(i);
 *  set(i,elem);
 *  get(i);

某个类,比如String、Student内部比较器只有一个,只能指定比较的规则,一般是使用频率最高的规则;

如果希望指定其他的更多比较规则,请使用外部比较器 外部比较器可以有多个

哈希码是如何添加数据的

添加数据共三步:

  1. 计算数据的哈希码(hashCode( )整数);(整数的哈希码就是本身)
  2. 根据哈希码计算存储位置;
  3. 存储到指定位置;
  • 如果指定位置已经存在元素,发生了冲突,(冲突不能完全避免,只能减少)

  • 发生了冲突之后就要调用equals( ) ,判断元素内容是否相同,如果相同,不添加(唯一);

  • 如果不相同,沿着链表继续比较,比较到最后也不相同,添加一个新的元素。

  • 存入哈希表三种情况:

    image-20191206103917207

image-20191206104126564

储存结构点睛之笔

哈希表的查询和删除速度也快

也是通过三步,基本上和存入差不多

hashCode() 和 equals( )到底有什么申请的作用?

  • hashCode():计算哈希码,是一个整数,根据哈希码可以计算出数据在哈希表中的存储位置
  • equals():添加时出现了冲突,需要通过equals方法进行比较,判断是否相同,查询时也需要使用equals进行比较,判断是否相同

MAP

map

  • 特点 key-value映射

HashMap

  • key 无序、唯一(Set)
  • Value 无序、不唯一(Collection)

LinkedHashMap

  • 有序的HashMap速度快

TreeMap

  • 有序 速度没有hash快

  • 问题:Set和Map有关系吗?
    • 采用了相同的数据结构,只用于map的key存储数据,就是Set.

Map集合详解:

* 存储国家简称和国家名的映射
 * 
 * Map:都是存储key-value键值对
 * 
 * HaspMap:底层结构是哈希表 查询快、添加开、无序
 *      key: 无序、唯一、HashSet
 *      value: 无序、不唯一 Collection
 *
 *LinkedHashMap:底层结构是哈希表+链表  查询快、添加快、有序
 *      key:有序(添加顺序)唯一 LinkedHashSet
 *      value:无序、不唯一 Collection
 *
 *TreeMap: 底层结构是红黑树 速度介于哈希表和线性表之间,有序
 *      key:有序(自然顺序)唯一、TreeSet
 *      value:无序    不唯一 Collection
 *
 * 常用方法
 *  map.put("us", "America");
 *  map.get("us");
 *  map.size();
 *  map没有迭代器,无法使用迭代器直接遍历,需要先变成Set,再遍历Set
 * 
 * Entry:Map接口中的内部接口 
 * 
 * map.keySet; 取key值,根据key取value值
 * map.entrySet();取key-value;
 * 
 * Set<Entry<String,String>> entrySet = map.entrySet();
   Iterator<Entry<String, String>> it = entrySet.iterator();
   
   

旧的集合类

版权声明:本文为liuwei0301原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/liuwei0301/p/12003734.html