java基础知识总结
最后更新于:2022-04-01 14:32:13
java在安卓的开发中是非常重要的,所以今天我总结了一下java的基础知识,当然,还有一些没有总结完,例如网络编程,io流等,将会在下一篇博文中写出。
## 概述
javac :负责的是编译的部分
java :负责运行的部分.会启动 jvm.加载运行时所需的类库,并对 class 文件进行执行
## 语法规则
### 数据类型
1 1 ): 基本数据类型:byte(1个字节)、short(2)、int(4)、long(8)、float(4)、double(8)、char(2)、boolean。
1个字节占8位
2 2 ): 引用数据 类型: 数组、类、接口。
### 运算符
> *+ - * / % %:任何整数模 2 不是 0 就是 1,所以只要改变被模数就可以实现开关运算
> &: 只有两边都为 true 结果是 true。否则就是 false。
> |:只要两边都为 false 结果是 false,否则就是 true
> & 和 && 区别: & :无论左边结果是什么,右边都参与运算。
&&: 短路与,如果左边为 false,那么右边不参数与运算。
> | 和 || 区别:|:两边都运算。
|| : 短路或,如果左边为 true,那么右边不参与运算。
> ++X(–X)表示在使用x之前,先使x的值增(减)1
### 语句
If switch do while while for
当判断固定个数的值的时候,建议使用 switch,效率相对较高。
当判断数据范围,获取判断运算结果 boolean 类型时,需要使用 if。
当某些语句需要执行很多次时,就用循环结构,建议使用 for。因为 for 循环完毕,变量在内存中释放。
### 函数
重载的定义是:在一个类中,如果出现了两个或者两个以上的同名函数,只要它们的参数的个数,或者参数的
类型不同,即可称之为该函数重载了。
如何区分重载:当函数同名时,只看参数列表。和返回值类型没关系。
### 数据
~~~
// 二分查找法。必须有前提: 数组中的元素要有序。
public static int halfSeach_2(int[] arr,int key){
int min,max,mid;
min = 0;
max = arr.length-1;
mid = (max+min)>>1; //(max+min)/2;
while(arr[mid]!=key){
if(key>arr[mid]){
min = mid + 1;
}
else if(key<arr[mid])
max = mid - 1;
if(max<min)
return -1;
mid = (max+min)>>1;
}
return mid;
}
~~~
java 分了 5 5 片内存。
1 :寄存器。2 :本地方法区。3 :方法区。4 :栈。5 :堆。
~~~
栈:存储的都是局部变量 ( 函数中定义的变量,函数上的参数,语句中的变量 );
只要数据运算完成所在的区域结束,该数据就会被释放。后进先出。
堆:用于存储数组和对象,也就是 实体。啥是实体啊?就是用于封装多个数据的。
1 :每一个实体都有内存首地址值。
2 :堆内存中的变量都有默认初始化值。因为数据类型不同,值也不一样。
3 :垃圾回收机制。
~~~
## 面向对象
### 类
属性是用于存储数据的 , 直接被访问,容易出现安全隐患 , 所以,类中的属性通
常被私有化,并对外提供公共的访问方法。
这个方法一般有两个,规范写法:对于属性 xxx ,可以使用 setXXX(),getXXX() 对其进行操作
主函数的存在,仅为该类是否需要独立运行 , 如果不需要,主函数是不用定义的。
主函数的解释:保证所在类的独立运行,是程序的入口,被 jvm 调用。
构造函数是在对象创建时,就被调用,用于初始化, 而且初始化动作只执行一次。
一般函数,是对象创建后,需要调用才执行,可以被调用多次。
### 封装
将不需要对外提供的内容都隐藏起来,把属性都隐藏,提供公共方法对其访问。
### this
用 this 调用构造函数,必须定义在构造函数的第一行。因为构造函数是用于初始化的,所以初
始化动作一定要执行。 否则编译失败。
### static
~~~
关键字,是一个修饰符 , 用于修饰成员( ( 成员变量和成员函数) )
静态方法只能访问静态成员,不可以访问非静态成员。
静态方法中不能使用 this ,super 关键字。
成员变量可以称为对象的特有数据,静态变量称为对象的共享数据。
静态代码块、构造代码块、构造函数同时存在时的执行顺序: 静态代码块 à 构造代码块 à 构造函数
~~~
### 单例设计模式
保证一个类在内存中的对象唯一性。
步骤:
1 1 ,因为创建对象都需要构造函数初始化 ,只要将本类中的构造函数私有化,其他程序就无法 再 创建
该类对象;
2 2 ,就在类中创建一个本类的对象 ;
3 3 ,定义一个方法,。 返回该对象,让其他程序可以通过方法就得到本类对象。 (作用:可控)
代码体现:
1 1 ,私有化构造函数 ;
2 2 ,创建私有并静态的本类对象 ;
3 3 ,定义公有并静态的方法,返回该对象
~~~
//饿汉式
class Single{
private Single(){} // 私有化构造函数。
private static Single s = new Single(); // 创建私有并静态的本类对象。
public static Single getInstance(){ // 定义公有并静态的方法,返回该对象。
return s;
}
}
//懒汉式:延迟加载方式。
class Single2{
private Single2(){}
private static Single2 s = null;
public static Single2 getInstance(){
if(s==null)
s = new Single2();
return s;
}
}
~~~
### 继承
java 中对于继承,java 只支持单继承。java 虽然不直接支持多继承,但是保留了这种多继承机制,进行改良。
java 支持多重继承。A 继承 B B 继承 C C 继承 D。
子类在进行对象初始化时,先调用父类的构造函数,这就是子类的实例化过程。
super()和 和 this() 不可以同时出现的构造函数中。
在方法覆盖时,注意两点:
1:子类覆盖父类时,必须要保证,子类方法的权限必须大于等于父类方法权限可以实现继承。否则,编译
失败。
2:覆盖时,要么都静态,要么都不静态。 (静态只能覆盖静态,或者被静态覆盖)
### final
可以修饰类,方法,变量。不可以被继承、覆盖。
### 抽象类
抽象类的特点:
1 1 : 抽象方法只能定义在 抽象类中 , 抽象类和抽象方法必须由 t abstract 关键字修饰 (可以描述类和
) 方法,不可以描述变量) 。
2 2 : 抽象方法只定义方法声明,并不定义方法实现。
3 3 : 抽象类不可以被创建对象( ( 实例化) ) 。
4 4 : 只有通过子类继承抽象类并覆盖了抽象类中的 所有 抽象方法后,该子类 才 可以实例化。否则,
该子类还是一个抽象类。
抽象类可以大一非抽象方法,抽象类中有构造函数。
### 接口
接口中有抽象方法,接口不可以实例化。 接口的子类必须实现了接口 中 所有的抽象方法后,该子类才可以实例化。否则,该子类还是一个抽象类。
类与类之间存在着继承关系,类与接口中间存在的是 实现关系。
继承用 extends ; 实现用 implements
### 多态
体现: 父类引用或者接口的引用指向了自己的子类对象。 //Animal a = new Cat();
instanceof ;// 判断对象是否实现了指定的接口或继承了指定的类
### Object
~~~
public boolean equals(Object obj){
if(!(obj instanceof Person))
return false;
Person p = (Person)obj;
return this.age == p.age;
}
~~~
通常 equals , toString , hashCode ,在应用中都会被复写 , 建立具体对象的特有的内容。
### 内部类
如果 A 类需要直接访问 B 类中的成员,而 B 类又需要建立 A 类的对象。这时,为了方便设计和访问,
直接将 A 类定义在 B 类中。就可以了。A 类就称为 内部类。内部类可以直接访问外部类中的成员。而外部类想要
访问内部类,必须要建立内部类的对象。
~~~
class Outer{
int num = 4;
class Inner {
void show(){
System.out.println("inner show run "+num);
}
}
public void method(){
Inner in = new Inner();//创建内部类的对象。
in.show();//调用内部类的方法。
}
}
~~~
匿名内部类:
当函数的参数是接口类型引用时,如果接口中的方法不超过 3 个。可以通过匿名内部类来完成参数的传递。
### 异常
> 通过 throws 关键字完成, 格式: throws 异常类名, , 异常类名
> throw 用于抛出异常对象,后面跟的是异常对象;throw 用在函数内。
throws 用于抛出异常类,后面跟的异常类名,可以跟多个,用逗号隔开。throws 用在函数上。
> 运行时异常,其中 Exception 有一个特殊的子类 RuntimeException,以及 RuntimeException 的子类是运
行异常,也就说这个异常是编译时不被检查的异常。
> finally 很有用,只要用户关闭资源。无论是否发生异常,资源都必须进行关闭。
System.exit(0); //退出 jvm,只有这种情况 finally 不执行。
常见 异常 :
1、脚标越界异常(IndexOutOfBoundsException)包括数组、字符串;
空指针异常(NullPointerException)
2、类型转换异常:ClassCastException
3、不支持操作异常;
### 包
常见的软件包:
> java.lang : language java 的核心包,Object System String Throwable jdk1.2 版本后,该
包中的类自动被导入。
> java.awt : 定义的都是用于 java 图形界面开发的对象。
> javax.swing: : 提供所有的 windows 桌面应用程序包括的控件, 比如: Frame , Dialog, Table, List
等等, , 就是 java 的图形界面库 。
> java.net : 用于 java 网络编程方面的对象都在该包中。
> java.io : input output 用于操作设备上数据的对象都在该包中。比如:读取硬盘数据,往硬盘写
入数据。
> java.util a : java 的工具包,时间对象 , 集合框架。
> java.applet : application+let 端 客户端 a java 小程序。 server+let – > servlet 端 服务端 java
小程序
### 多线程
创建线程:
方法1:
~~~
步骤:
1,定义类继承 Thread 类;
2,目的是复写 run 方法,将要让线程运行的代码都存储到 run 方法中;
3,通过创建 Thread 类的子类对象,创建线程对象;
4,调用线程的 start 方法,开启线程,并执行 run 方法。
~~~
方法2:
~~~
步骤:
1,定义类实现 Runnable 接口。
2,覆盖接口中的 run 方法(用于封装线程要运行的代码)。
3,通过 Thread 类创建线程对象;
4,将实现了 Runnable 接口的子类对象作为实际参数传递给 Thread 类中的构造函数。
为什么要传递呢?因为要让线程对象明确要运行的 run 方法所属的对象。
5,调用 Thread 对象的 start 方法。开启线程,并运行 Runnable 接口子类中的 run 方法。
Ticket t = new Ticket();
/*
直接创建 Ticket 对象,并不是创建线程对象。
因为创建对象只能通过 new Thread 类,或者 new Thread 类的子类才可以。
所以最终想要创建线程。既然没有了 Thread 类的子类,就只能用 Thread 类。
`*/`
Thread t1 = new Thread(t); //创建线程。
/*
只要将 t 作为 Thread 类的构造函数的实际参数传入即可完成线程对象和 t 之间的关联
为什么要将 t 传给 Thread 类的构造函数呢?其实就是为了明确线程要运行的代码 run 方法。
`*/`
t1.start();
~~~
### 同步
同步函数:其实就是将同步关键字定义在函数上,让函数具备了同步性。
同步函数使用的锁是 this , 静态同步函数的锁是 该类的字节码文件对象。
同步是隐示的锁操作,而 k Lock 对象是显示的锁操作,它的出现就替代了同步。
## API
### 字符串
~~~
parseInt(string,radix); //将给定的数转成指定的基数进制;
在 在 5 jdk1.5 版本后,对基本数据类型对象包装类进行升级。在升级中,使用基本数据类型对象包装类可
以像使用基本数据类型一样,进行运算。
Integer i = new Integer(4); 5 //1.5 版本之前的写法;
Integer i = 4; // 自动装箱 ,5 1.5 版本后的写法;
i = i + 5;
//i 对象是不能直接和 5 相加的,其实底层先将 i 转成 int 类型,在和 5 相加。而转成 int 类型的操作是隐
式的。 自动拆箱:拆箱的原理就是 i.intValue();i+5 运算完是一个 int 整数。
~~~
### 集合框架
1:对象封装数据,对象多了也需要存储。 集合用于存储对象。
2:对象的个数确定可以使用数组,但是不确定怎么办?可以用集合。因为
### List接口
~~~
List : 有序( ( 元素存入集合的顺序和取出的顺序一致) ) ,元素都有索引。元素可以重复。
| | -- ArrayList : 底层的数据结构 是数组, , 线程不同步 ,A At rrayList 了 替代了 Vector , 查询元素的速
度非常快。
| | -- LinkedList : 底层的数据结构是链表 , 线程不同步 , 增删元素的速度非常快。
| | -- Vector : 底层的数据结构就是数组 , 线程同步的 ,r Vector 无论查询和增删都巨慢。
~~~
对于 t list 集合,底层判断元素是否相同,其实用的是元素自身的 s equals 方法完成的。所以建议
元素都要复写 s equals
~~~
LinkedList : 的特有方法。
addFirst();
addLast();
在 jdk1.6 以后。
offerFirst();
offerLast();
getFirst():获取链表中的第一个元素。如果链表为空,抛出 NoSuchElementException;
getLast();
在 jdk1.6 以后。
peekFirst();获取链表中的第一个元素。如果链表为空,返回 null。
peekLast();
removeFirst():获取链表中的第一个元素,但是会删除链表中的第一个元素。如果链表为空,抛出
NoSuchElementException
removeLast();
在 jdk1.6 以后。
pollFirst();获取链表中的第一个元素,但是会删除链表中的第一个元素。如果链表为空,返回 null。
pollLast();
~~~
### Set接口
当元素的 hashCode 值相同时,才继续判断元素的 equals 是否为 true。
~~~
TreeSet:
用于对 Set 集合进行元素的指定顺序排序,排序需要依据元素自身具备的比较性。
如果元素不具备比较性,在运行时会发生 n ClassCastException 异常。
所以需要元素 实现 e Comparable 接口,强制让元素具备比较性, 复写 o compareTo 方法。
~~~
### Map集合
– Hashtable :底层是哈希表数据结构,是线程同步的。不可以存储 null 键,null 值。
– HashMap :底层是哈希表数据结构,是线程不同步的。可以存储 null 键,null 值。替代了 Hashtable.
– TreeMap :底层是二叉树结构,可以对 map 集合中的键进行指定顺序的排序。
### 把 把 p map 集合转成 t set 的方法
Set keySet();
Set entrySet(); //取的是键和值的映射关系。
~~~
取出 p map 集合中所有元素的方式一 : keySet() 方法。
可以将 map 集合中的键都取出存放到 set 集合中。对 set 集合进行迭代。迭代完成,再通过 get 方法对获取
到的键进行值的获取。
Set keySet = map.keySet();
Iterator it = keySet.iterator();
w w hile(it.hasNext()) { {
Object key = it.next();
Object value = map.get(key);
System.out.println(key+":"+value);
} }
取出 p map 集合中所有元素的方式 二 : entry Set() 方法。
Set entrySet = map.entrySet();
Iterator it = entrySet.iterator();
while(it.hasNext()) {
Map.Entry me = (Map.Entry)it.next();
System.out.println(me. getKey()+"::::"+me. getValue());
~~~
### 使用集合的技巧:
~~~
看到 Array 就是数组结构,有角标,查询速度很快。
看到 link 就是链表结构:增删速度快,而且有特有方法。addFirst; addLast; removeFirst(); removeLast();
getFirst();getLast();
看到 hash 就是哈希表,就要想要哈希值,就要想到唯一性,就要想到存入到该结构的中的元素必须覆盖
hashCode,equals 方法。
看到 tree 就是二叉树,就要想到排序,就想要用到比较。
比较的两种方式 :
一个是 Comparable : 覆盖 o compareTo 方法 ;
一个是 Comparator : 覆盖 e compare 方法。
LinkedHashSet,LinkedHashMap:这两个集合可以保证哈希表有存入顺序和取出顺序一致,保证哈希表有序。
集合什么时候用?
当存储的是一个元素时,就用 Collection。当存储对象之间存在着映射关系时,就使用 Map 集合。
保证唯一,就用 Set 。不保证唯一 , 就用 List
~~~
### 双列集合 Map
~~~
Map map = new HashMap();
map.put("a", "aaa");
// 传统方式:必须掌握这种方式
Set entrys = map.entrySet(); // 1.获得所有的键值对 Entry 对象
iter = entrys.iterator(); // 2.迭代出所有的 entry
while(iter.hasNext()) {
Map.Entry entry = (Entry) iter.next();
String key = (String) entry.getKey(); // 分别获得 key 和 value
String value = (String) entry.getValue();
System.out.println(key + "=" + value);
}
~~~
### 泛型
当类中的操作的引用数据类型不确定的时候,以前用的 t Object 来进行扩展的,现在可以用泛型来表示。这样可以避免强转的麻烦,而且将运行问题转移到的编译时期。
~~~
class Tool<Q> {
private Q obj;
public void setObject(Q obj) {
this.obj = obj;
}
public Q getObject() {
return obj;
}
}
~~~
### Data和日历类
将日期字符串转换成日期对象 :是 使用的就是 DateFormat 方法中的 Date parse(String source)
~~~
public static void method(){
Calendar c = Calendar.getInstance();
System.out.println(c.get(Calendar.YEAR)+"年"+(c.get(Calendar.MONTH)+1)+"月"
+getNum(c.get(Calendar.DAY_OF_MONTH))+"日"
+"星期"+getWeek(c.get(Calendar.DAY_OF_WEEK)));
}
public static String getNum(int num){
return num>9 ? num+"" : "0"+num;
}
public static String getWeek(int index){
/*
查表法:建立数据的对应关系.
最好:数据个数是确定的,而且有对应关系。如果对应关系的一方,是数字,而且可以作为角标,那么可以
通过数组来作为表。
*/
String[] weeks = {"","日","一","二","三","四","五","六"};
return weeks[index];
}
~~~