类包含于对象,是对象中的属性,方法间的集合
对于对象的抽象,是java中引用类型,是创建对象的模版,对象是类的具体实例,
类关键字:public class
属性可以称为成员变量, 方法:行为(对象名小驼峰)
类名大驼峰
形参:定义方法中使用的临时变量,专注于数据类型
实参:调用方法时候,实际传入的数据
byte
short
int
long
可变参数(...) 可以传递任意个(0个)
string...arg 放到最后一个位置,传参可以传递字符串数组(数组)或者字符串(一个),内部当作数组处理
返回值和返回类型
方法执行后向外部返回的数据 +return 所有方法都要返回类型(void 是特殊的返回类型)
package
包分为:项目包(公司域名倒写+项目名,不能+s),工程包,
遵循java命名规范:字母数字下划线美元,区分英文大小写,数字不能开头,不能有关键字,保留字
(公司名+项目名字倒着写),包位置在首行,全部小写,不同层级用.
,导入包导入包的位置
同一包不用导,java.lang不用导包
通配符*号,当前包下的所有
构造方法:
语法规则:方法名和类名相同,没有返回值
如何调用,new 的时候会默认调用
隐式构造:类中没有显式提供构造方法,系统创建无参的构造器,
面向对象的三大特性:封装,继承,多态
封装为了实现高内聚,低耦合(模块功能越强大越好,多个类之间,联系越少越好)
属性设置为private,提供setter和getter
继承:extends
当然不是父类所有都可以被继承,private(私有的不能被继承)
this()构造方法,this.属性,this调用自身的属性和方法.
一般不用+this,除非属性名和形参名重名
this()。调用自身的构造方法,必须放到首行
this表示自身,表示当前对象本身
super:
super调用父类的属性和方法
--当形参名和父亲属性名重合,或者子类的方法和父类的方法名一致,加super,表示调用父类的
super()调用父类的构造方法,必须放到首行
访问权限
public:公开的
protected:本包和子类,
default:本包
private,当前类
final -最终的
final修饰变量,转为常量
常量如何命名:全部大写,不同单词使用下划线分割
用法:配合static一起使用
修饰方法,无法被子类重写
修饰类,无法被继承
final优点:处理速度快,如同String
类变量/类方法:static修饰的静态变量和静态方法
变量:静态变量,静态方法,构造代码块
实例变量/实例方法
static调用:static使用类名,直接调用
static内容一旦分配内存,则无法释放,直到程序终止
方法重写VS重载
方法重载:同一个类,两个方法的方法名字相同,参数不同,一同一不同,构造方法可以重载
方法重写:子类覆盖父类
二同:方法名和传递参数一致,参数列表相同
二小返回类型小于等于父类 子类抛出的异常范围小于父类
一大,访问权大于等于父类
接口本身是抽象的,所以可以用abstract修饰,并且内部的成员变量public static final
成员方法public abstract
abstract:抽象方法的关键字
具有抽象方法的类叫做抽象类,关键字abstract
抽象类和抽象方法的注意事项:
1.抽象类中没有抽象方法,但是无意义
2.抽象类具有普通类中的所有成分
3.子类继承抽象父类,或者重写抽象方法,或者将子类定义为抽象类
4.抽象无法实例化对象,只能被子类继承使用
那么抽象类中是否可以有构造方法-可以(在子类中,子类去调用父类的构造方法)
接口和抽象类的区别
1常规的extends和interface,这两个不一样就不用说了
2.抽象类,extends我只能继承一个,但是接口大多场景都是需要用很多个的,比如说一个小米充电器,我是不是要遵守什么快充的协议,同时还要遵守电源插排的规格,还要支持typeC的型号。
3.抽象类可以自己去实现方法,不去定义为抽象,但是接口就必须定义为抽象,比如有些方法是共有的,比如电脑和手机,平板都有这个开机功能,那么方法我就可以不去实现了,但是你假如说用接口,那么各个类之间就必须去实现彼此的开机功能。
内部类:
可以将多个类写在一个文件中,叫内部类(不在里面写呗,他会被当成另一个类,并且给你生成该类的文件)
多个类在一个文件中,最多只有一个类是public
将类写在另外的类的内部,叫做内部类
优缺点:
优点:内部类可以直接使用外部类的所有属性和方法,包括private
缺点:破坏了类的结果,并且内部类的实例化方法比较复杂
内部类的分类:成员内部类,局部内部类,匿名内部类
匿名内部类:一般都是直接实现接口啥的
enum统一管理状态常量,enum里面都是static,final
枚举可以用方法的参数,但是不建议作为方法的返回值
1.==
- 判断两个数值是否相等,属于比较运算符
- 判断两个对象的内存地址是否一致
2.equals()
- 默认是比较两个对象的内存地址是否一致
- 根据业务需求,可以重写equals,改变其判断逻辑,比如String(重写equals方法,将判断逻辑改为两个字符串的判断)
3.hashCode()
- 默认是返回对象的内存地址的哈希码
- 如果重写equals方法,一般需要重写hashCode,达到两者的逻辑基本一致,重写hashCode,将参与equals判断的属性作为hashCode计算
4.toString()
- 默认是打印字符串的内存地址
- 一般会重写toString方法,打印对象的属性
基本类型包装类/封装类
1.为什么要有包装类?包装类和基本类型的区别
基本类型功能单一,只可以简单运算
包装类扩展了功能,更符合面向对象的思想
哪些包装类
Boolean,Byte,Interger,Short,Long,Character,Float,Double,
Integer:静态常量 MAX_VALUE,MIN_VALUE
自动拆箱,装箱,与字符串的相关切换
UUID:唯一不重复的ID;
ArrayList:基于数据,查询方便,支持随机访问,扩容1.5倍+1
因为要搬运节点,所以插入和删除麻烦,但是尾插可能会方便一点
LinkedList:基于双向链表,插入和删除方便,因为不用牵扯后续节点
Map映射:
使用key和value表示一对数据
key不重复,value可以重复
key和value是java任意引用类型
扩容2倍
map的实现子类HashMap和TreeMap
put-添加数据
remove-删除数据
get(根据key获取value)
clear清空集合
containsKey(Key)判断是否包含指定key
isEmpty()判断是否为空
map.size()获取当前集合大小
Set<String>keys=map.keySet()
遍历三种方法:
for(String key:keys)
获取key和value组成的集合,根据对象取得的key和value
for(Map.Entry<String,String>>entries=map.entrySet();
Java8的Lambda表达式
map.forEash(key,value)->{
sout(key)
sout(value)
});
Collections:集合
Collections包含方法:
reverse 逆转
shuffle 随机打乱排序
rotata(list,int x)旋转把后面的往前调换位置过来(相对顺序不变)
replaceAll(list,"A","X")把A字符串换成X
函数式接口 function interface接口中有且只有一个抽象方法的接口
Runnable. Comparator
lambda :箭头函数,函数的简写(参数列表){
逻辑代码
}
不用写类型
lambda规则:参数列表只有一个时候,省略()
有且只有1行代码时候,省略{}
return 有return 不能省略{},如果只有一行代码,可以省略return和{}
forEach也可以用lambda
Stream:流的创建 流是用来运算的,集合是用来存储数据的
List<String>list=new ArrayList<>();
list.add("A")
Stream <String>a=list.stream();集合流的创建
Stream <String>a=Arrays.stream(arr);
空的流
Stream<String>empty=Stream.empty()
Stream<String>stream=Stream.of("A","B","C");
filter:过滤器
Stream<Integer>m=stream.filter( item->item>0) lambda表达式
Stream<Integer>new=stream.distinct去重
Stream<Integer>new=stream.limit(2) 限制取前面两个数据
skip跳过。跳过前面几个取后面的
map映射,将原先有的数据按照指定规则变成新的数据
Stram<Integer>new=stream.map(item->item+10);
flatMap将原有的数据,映射陈流的数据,最终把所有的流合并
Stram<String>new =stream.flatMap<(item->{
//item :"aa,bb","cc,dd"
String []a=item.split(",");
return Arrays.stream(arr) //"aa","bb"})
newStream.forEash(System::println)
终端处理,只能用一次就关闭流了。
count()
接口的组成部分:
java8之前:共有的静态常量,共有的抽象方法
java8之后:default,可以按照需求实现。静态方法static,接口名字可以直接调用(新增的)
异常:代码在编译或者运行时候发生的不正确的事情
系统默认的异常处理,通常是把异常信息打印到控制台,终止程序运行
异常结构
Throwable. -Error
-Exception异常,代码引起的,编译时异常和运行时异常
编译时候的异常比如IOException和FileNotFoundException
运行时异常:ArithmeticException
数据下标越界异常 ArrayIndexOutOfBoundsException
StringIndexOutBountdsException字符串下标越界
NullPointException空指针
ClassCastException类型转换异常
File对象的创建
file("文件路径")
getName获取文件名字包括后缀名
getAbsolutepath()获取绝对路径
getParent()获得父目录路径
选择心得:
值传递和引用传递:只要不是基本类型和字符串都可以说是引用传递(传递地址的值传递随便你怎么说)
子类继承父类的时候,假如有父类有没有重写构造方法,子类会默认调用父亲的无参构造方法,假如你重写了,那么你自己去手动调用父亲构造方法
综合题
1.标识符的命名规则:
- 由英文字母,数字,下划线,$组成
- 不能以数字开头
- 区分英文大小写
- 不能包含空格
2.Java中数据类型转换哪两种:
- 自动类型转换:编译器自动完成类型转换,不需要程序中编写代码
- 强制类型转换:强制编译器完成类型转换,需要在程序中编写对应代码
3.break和continue区别
- break可以退出当前循环,并且退出整个循环,执行循环外的条件
- continue是退出当前循环,执行下一次循环,并且会再次判断条件是否符合来决定是否进行continue
4.类和对象的关系
- 类是模版,是具有相同属性和行为的对象的集合
5.抽象类和接口之间的区别:
- 抽象类是抽象方法和非抽象方法的集合,抽象类不能被实例化,抽象方法不能被static修饰,类中有抽象方法,那么这个类一定是抽象类()。
- 接口,接口是抽象类的变化,接口无法被实例化,接口内不能存在构造方法,接口中所有变量都是public static final修饰,方法大多数都是抽象方法public abstract,都是默认添加这些修饰符,一般来说抽象类强调的属性,接口强调方法,类只能单继承,但是可以实现多个接口(1.8中有了default方法体的实现,默认方法与静态方法的添加)
6.抽象类
- 抽象类自身无法实例化,但是子类可以创造对象,抽象类关键字abstract,父类定义的抽象方法,子类必须实现(即方法重写)
- 抽象方法没有方法体
- 抽象方法必须定义在抽象类中
7.static函数或者变量有什么特点
- 限制变量的作用域(static全局变量)
- 设置变量的存储域(static局部变量)
8.单例模式作用
- 保证了一个类只有一个实例,并且提供一个全局的访问点
9.实现单例模式的三个关键点
- 构造方法私有化
- 定义一个静态实例
- 提供可以返回静态实例的静态方法
10.error和Exception的区别
error是系统级的错误,Java环境内部或者系统硬件出现问题,不能指望程序处理这样的问题,除了退出之外别无选择,他是java虚拟机抛出的,exception表示需要程序捕捉,需要处理的异常,由程序设计不完善而出现的问题,程序必须处理的问题。
11.final,finally,finalize区别
- final是声明变量,方法和类的,分别表示变量值不可变,方法不可覆盖,类不可以被继承
- finally是处理异常的关键字,finally{}内部的代码一定会被执行
- finalize是Object类的一个方法,在垃圾回收的时候,会调用该回收对象的此方法
12.请列举异常处理的五大关键字,并说明各自的作用
- try捕获程序中运行中的Exception
- catch捕获程序运行中出现的Exception
- throw抛出Exception
- throws方法里面要抛出的异常
- finally,不管运行结果如何,都会被执行的语句
13.5个常见的异常
- ArrayIndexOutBoundsException
- StringIndexOutBoundsException
- NullPointerException
- ArithmeticException
- IOException
- ClassCastException
- FileNotFoundException
进程 (Process)
计算运行中的程序叫做进程
每个进程拥有独立的内存单元
线程: (Thread)
进程中的一条执行流程
进程中运行多个线程存在,不同线程共享改进程的内存单元
进程中必须有一个主线程
线程的创建方式与启动:
1.继承Thread
public class CountThread extends Thread{ @Override public void run(){ } Thread th=new CountThread(); th.start();
1.3线程的理解:
程序中多个线程抢夺cpu执行权,谁抢到谁执行
是否可以手动调用run()启动线程,不能,假如手动调用run,就相当于在主线程中调用run就是抢占了主线程的操作(主线程先执行run,执行完毕执行自己的方法)
2.实现Runnable接口
implement Runnable
继承Thread需要实现run方法,
Runnable不是线程,他本质是线程需要执行的任务(更好,1.JAVA类单继承)
3.使用Callable接口
call回调(给予调用者返回数据)(缺点:容易造成线程阻塞,(你不要去获取结果,假如要获取结果,就会一直阻塞,直到执行完毕,才会开始往下走)
1.实现Callable接口(范型必须是引用类型) class CountCallable implements Callable<Integer>{ //打印0-99,对外返回0-99 @override pulic Interger call()throw Exception(){... } 创建FutureTask对象,参数是Callable Main{ main{ //把回调接口,放到未来任务里面执行 FutureTask<Integer>futureTask=new FutureTask<Integer>(new CountCallable()); Thread a=new Thread(futureTask); } }
生产者消费者模式:
适用于临界资源的添加或者减少,比如库房管理(store),针对满和空会进行阻塞
库房满了恢复取决于出库,空了取决于入库。
Producer - Consumer
力扣234.回文链表
来这个之前,先回顾一下逆置链表
下面代码如何思考的呢
从这一步开始,慢慢往后走就行了,注意cur不要放在第一个位置开始,其余就很简单了
//此时slow 有可能在正好中间,也有可能在两边的左边,需要看fast
ListNode pHead=new ListNode();
ListNode cur=slow.next;
pHead.next=slow;
ListNode preCur=slow;
while(cur!=null){
ListNode curNext=cur.next;
cur.next=pHead.next;
preCur.next=curNext;
pHead.next=cur;
cur=curNext;
}
这个代码还是有难度的,你需要先找到一个中间节点,然后把节点后面的逆置,之后,我们再从他的头节点,与他逆置的节点开始互相比较,因为假如逆置后,全部相同,那么就说明是回文链表。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public static boolean isPalindrome(ListNode head) {
ListNode fast=head;
ListNode slow=head;
while(fast!=null&&fast.next!=null){
fast=fast.next.next;
slow=slow.next;
}
//此时slow 有可能在正好中间,也有可能在两边的左边,需要看fast
ListNode pHead=new ListNode();
ListNode cur=slow.next;
pHead.next=slow;
ListNode preCur=slow;
while(cur!=null){
ListNode curNext=cur.next;
cur.next=pHead.next;
preCur.next=curNext;
pHead.next=cur;
cur=curNext;
}
slow=pHead.next;
//此时我把后面的已经逆置了
while(slow!=null){
if(head.val!=slow.val)return false;
head=head.next;
slow=slow.next;
}
return true;
}
}