访问修饰符(pubic,protected,默认,private)-->非访问修饰符(static,final,abstract)-->接口(interface)-->异常(error,exception)-->多重捕获机制和异常抛出机制-->File文件类-->IO流
-- 修饰符主要分为两类
非访问修饰符和访问修饰符
-- 访问修饰符
权限
public,公共的,本类,同一个包下,非同一个包(子类),非同一个包(非子类)
protected,受保护的,本类,同一个包下,非同一个包(子类)
默认修饰符,默认的,本类,同一个包下,
private,私有的,本类
-- 非访问修饰符
1,static,静态
可以修饰类本部类,变量,函数
类在加载到内存的时候是最先加载进来的部分是静态成员
静态成员的访问不需要依赖对象,可以直接通过类名来访问
静态成员的内存中只保存一份,声明周期跟类保持一致,所以静态成员是共享的
一般一些不常改动的数据适合声明为静态的(函数不需要访问到类的非静态的变量时,才建议使用静态函数)
例子1
public class StaticDemo {
private int aa=4;//全局变量
static{
System.out.println("我是一个静态代码块");
}//在调用函数时,只执行一次静态代码块
public static void main(String[] args) {
StaticDemo staticDemo=new StaticDemo();
StaticDemo staticDemo2=new StaticDemo();
staticDemo.showName();
StaticDemo.showName();//被static修饰的函数,可以直接用类名去调用
staticDemo.showAge();//没有被static修饰的函数,不可以用类名调用,只能拿对象调用
}
public StaticDemo(){
System.out.println("StaticDemo.StaticDemo()");
}
public static void showName(){//被static修饰的类
System.out.println("briller");
//被static修饰的函数,不可以访问全局变量,静态函数里只能够访问静态的成员变量
//因为static最先被加载,这个时候全局变量还没有被加载,所有想要访问全局变量,需要变量是静态的
}
public void showAge(){//不被static修饰的类
System.out.println(23);
System.out.println(aa);//没有被static修饰的函数,可以访问全局变量
}
}
2
public class Student {
private static int age;//被静态修修饰符定义的属性,静态成员的内存中只保存一份
private static String name;//所以只会保存一份数据,取最后一份数据
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student(int age, String name) {
super();
this.age = age;
this.name = name;
}
public Student(){
}
@Override
public String toString() {
return "age="+this.age+",name="+this.name;
}
}
3
public class StaticDemo2 {
public static void main(String[] args) {
Student student1=new Student();
student1.setAge(23);
student1.setName("zs");
System.out.println(student1);//打印student1数据
Student student2=new Student(24,"张三");
System.out.println(student1);
//属性是静态的,所以只会打印出最后一份数据,student1被student2覆盖
System.out.println(student2);
}
}
2,final,最终的
被final修饰的变量,它的值不能再做修改
被final修饰的函数,不能被重写
被final修饰的类,不能被继承
例子1
public class FinalDemo {
private final int a=2;//被final修饰的变量,它的值不能再做修改
public static void main(String[] args) {
FinalDemo finalDemo =new FinalDemo();
finalDemo.testfinal();
}
public final void testfinal(){
// a=4;//被final修饰的变量,它的值不能再做修改
// System.out.println(a);
}
}
2
public class Parent {//创建父类
public final void test1(){//final修饰的函数,不能被调用
System.out.println("Parent.test1()");//快捷键syst
}
public void test2(){//不被final修饰的函数
System.out.println("Parent.test2()");
}
}
3
public class Child extends Parent {//被final修饰的类,不能被继承,不被final修饰的类才能被继承
public static void main(String[] args) {
Parent child=new Child();
child.test1();
child.test2();
}
@Override//能重写test2,不能重写test1,被final修饰的函数,不能被重写
public void test2() {
// TODO Auto-generated method stub
super.test2();
}
}
3,abstract,抽象的
-- 28接口
接口是一种规范和标准,他们可以约束类的行为,是一些方法特征的集合,但是没有方法的实现。
-- 特点
1.接口里面的所有方法都是抽象的;public修饰,abstract类型,不能存在实现了的方法
2.接口里面的成员变量(全局变量)必须是public修饰static final类型。
static静态,final最终的,不能被改变的,换句话说就是变量的值必须是常量。
3.接口里不能含有静态的方法(因为静态函数有函数体,但是接口函数不能有函数体)(1.8版本可行)
4.接口不能实例化,所以接口是不能定义任何构造函数
5.接口可以多继承,一个接口可以继承自多个接口,
-- 语法
修饰符 interface XX{};
(接口有{},接口的函数没有{函数体})
-- 以Worker为例
-- 接口解决什么问题
1.类型解耦
2.代码更方便维护
3.提高程序的扩展能力
1.
public class WorkUtil {
//获取每一种劳动者做的工作职责
/*public static void showCookerWork(Cooker cooker){//声明接口类型,一个一个声明
cooker.work();
}
public static void showProgramerWork(ProgramerWork programerWork){
programerWork.work();
}
public static void showTeacherWork(Teacher teacher){
teacher.work();
}
public static void showTesterWork(Tester tester){
tester.work();
}*/
public static void showWorker(Worker worker){//声明接口类型,使用worker声明直接声明
worker.work();
}
}
2.
public class Tester2 {
public static void main(String[] args) {
/* Cooker cooker=new Cooker();
WorkUtil.showCookerWork(cooker);//拿类调用对象,因为调用的函数是静态函数
WorkUtil.showTeacherWork(new Teacher());
WorkUtil.showProgramerWork(new ProgramerWork());
WorkUtil.showTeacherWork(new Tester());*/
WorkUtil.showWorker(new Cooker());//接口类型接收实现类对象,类型解耦
WorkUtil.showWorker(new Teacher());
WorkUtil.showWorker(new ProgramerWork());
WorkUtil.showWorker(new Tester());
}
}
3.
public class Cooker implements Worker {//实现类
@Override
public void work() {
System.out.println("厨师");
}
}
public class ProgramerWork implements Worker{//实现类
@Override
public void work() {
System.out.println("程序员");
}
}
public class Teacher implements Worker{//teacher实现类,类实现一个接口用的关键字implements
@Override
public void work() {
System.out.println("老师");
}
}
public class Tester implements Worker {
@Override
public void work() {
System.out.println("测试");
}
}
-- 29 abstract,抽象的
定义了抽象方法的类叫抽象类
-- 语法
修饰符 abstract class XX{}
前面在讲接口的时候,接口是定义的一套标准,可以约束类的行为,因为实现类都需要实现这
一套方法。我们接口不能定义实现的函数,而抽象类可以,抽象类既可以定义抽象的方法来约
束子类的行为,还可以定义实现方法,对于一些子类共有的实现方法,我们可以把他们抽出来
放到抽象类里面,子类直接从抽象类里面继承
子类有共性行为的,希望继承父类,不是共性行为可以先定义在父类里面,在继承的时候做个性化设置,
所以就是用抽象类定义父类,抽象类定义的方法,子类都需要写实现的方法
1.父类
public abstract class Student {
String study(){//实现的方法
return "上课";
}
abstract String classNumber();//抽象的方法
//抽象类,函数是抽象的时候需要声明abstract,不声明默认是实现类public static
//因为抽象类既可以定义抽象的方法来约束子类的行为,还可以定义实现方法
abstract String getType();
}
2子类
public class PrimaryStudent extends Student{
@Override
String classNumber() {
// TODO Auto-generated method stub
return "4节课";
}
@Override
String getType() {
// TODO Auto-generated method stub
return "小学生";
}
public class JuniorStudent extends Student {
@Override
String classNumber() {
// TODO Auto-generated method stub
return "6节课";
}
@Override
String getType() {
// TODO Auto-generated method stub
return "初中生";
}
}
public class SupperStudent extends Student{
@Override
String classNumber() {
// TODO Auto-generated method stub
return "8节课";
}
@Override
String getType() {
// TODO Auto-generated method stub
return "高中生";
}
}
3调用
public class Tester1 {
public static void main(String[] args) {
Student [] students={new PrimaryStudent(),new JuniorStudent(),new SupperStudent()};
StudentUtli.show(students);
}
}
-- 30
普通类和抽象类区别:
普通类能够定义的成员抽象类都能定义,唯一的区别就是抽象类还可以定义抽象的方法
抽象类和接口的区别:
抽象类可以像接口一样去定义抽象的方法,static final类型的变量,其他抽象类能定义的成员接口都定义不了
-- debug的用法
使用debug as运行程序,查看并调试
breakpoint properties勾选conditional添加条件,当满足条件时断点
-- 31异常
代码运行过程中出现非正常的情况
-- 分类
error
一般指与jvm虚拟机相关的严重错误,如系统崩溃,虚拟机错误,内存溢出等。这一类错误往往会导致应用程序直接中断,
仅靠程序本身无法恢复和预防,并且遇到这种情况,建议直接中断
exception
表示程序可以处理的异常情况,可以通过直接捕捉这些异常,使程序继续执行,也可以选择不处理,让程序终止,
而不是随意让程序终止
相同点:继承同一个类throwable。
ctrl+shift+t,快捷键,快速打开类
ctrl+t,查看类的关系
Alt+方向键,类的前后切换快捷键
--常见的error
可以通过ctrl+shift+t查找类,在通过ctrl+t,查看类的关系
例如error类
NoSuchMethodError没有此方法的错误
OutOfMemoryError内存溢出的错误
StackOverflowError栈溢出的错误
ThreadDeath线程锁死
-- exception分为两类
1,编译时异常(检查性异常),直接继承Exception类
2,运行时异常(非检查性异常),直接继承RuntimeExcepion
编译时异常:编译器在编译你的代码的时候发现你的代码肯能会出现的问题,
就会提示你要去手动处理这个异常,否则代码编译不通过,所以叫编译时异常肯能会出现的问题。
当出现运行问题时异常的时候,程序直接中断了,但是也可以通过异常处理机制,
捕获到异常,恢复程序的继续执行
运行时异常:编译时发现不了的问题,但是代码运行过程中
-- 常见的编译性异常exception
ClassNotFoundException, 找不到类
InstantiationException, 当视图使用class类中的newlnstance方法
创建一个类的实例,目标类无法实例化
IllegalAccessException, 拒绝访问目标类
NoSuchMethodException, 请求的方法不存在
SecurityException
InterruptedException,一个线程被另一个线程中断,抛出该异常
-- 常见的运行时异常
ArithmeticException
ArrayIndexOutOfBoundsException数组下标越界
NullPointerException空指针异常
IndexOutOfBoundsException索引越界
ClassCastException强制转换异常
-- 32异常处理机制
1.异常直接抛出给上一级调用者去处理,直到处理,直到所有上级调用者都不处理就会java虚拟机处理
2.通过try..catch来捕捉处理异常,语法如下
try{
...//try代码块
}catch(XX exception e){
...//catch代码块
}
try块指的是受保护的代码,肯能会抛出异常的代码,catch后面的小括号是抓去的异常,
这个异常可以被当做参数传入catch块,catch块是抓取到异常后的处理逻辑,
而处理逻辑一般是这么几种(做日志,将异常重新封装后抛出,其他逻辑)
-- 多重捕获机制
try后面可以使用多个catch语句取捕获受保护代码中抛出的每一种异常,
多重捕获语法
try{
...//受保护的代码
}catch(异常类型1, 异常变量1){
...//代码
}catch(异常类型2, 异常变量2){
...//代码
}catch(异常类型3, 异常变量3){
...//代码
}catch(异常类型4, 异常变量4){
...//代码
}
1,匹配规则:如果抛出的异常不属于类型1,则继续往下判断,直到找到匹配类型
2,catch 的异常类型中如果有父子类型,那么子类型应该要放在前面,其他没联系的异常,顺序之间没有要求
1
public class ExceptionDemo1 {
public static void test1() throws ChildException{
//如果方法里发生了一个编译时异常(检查时异常),而代码里面没有将其捕获
//则必须使用throws关键字写在方法签名的后面
throw new ChildException();
//在方法里抛出一个捕获的异常或者自己创建的异常,使用throw关键字
}
public static void test2() throws ParentException {
throw new ParentException();
}
}
3
public class MultiCatch {
public static void main(String[] args) {
try {
ExceptionDemo1.test1();
ExceptionDemo1.test2();
} catch (ChildException e) {//子
// TODO Auto-generated catch block
e.printStackTrace();
}catch (ParentException e) {//父
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
-- 异常抛出机制
使用throw/throws关键字抛出异常
1,在方法里抛出一个捕获的异常或者自己创建的异常,使用throw关键字
2,如果方法里发生了一个编译时异常(检查时异常),而代码里面没有将其捕获
则必须使用throws关键字写在方法签名的后面
3,跑出去的编译时异常会传给上一级调用者,所以上一级调用者也需要强制处理,或者抛出,或捕获
-- finally关键字
可以在try...catch代码块后面加一个finally的代码块,语法如下
try{
...//受保护的代码
}catch(异常类型1, 异常变量1){
...//代码
}catch(异常类型2, 异常变量2){
...//代码
}finally{
...//finally代码块
}
无论是否发生异常,finally代码块中的代码总会被执行
finally中的代码一般用来回收资源,做一些收尾工作的事情
-- throwabl1e类的方法
getMessage():获取详细的异常描述信息
getCause():获取发生异常的起因
getStackTrace():打印异常发生时的方法调用栈信息
-- 自定义异常
为什么要自定义异常?
异常提示信息不够友好,自定义异常做封装,给代码一个友好的错误提示
实现方式
1,自定义一个编译性异常:继承于Exception
2,自定义一个运行时异常:继承于RuntimeException
3,覆盖父类或者超类的某些方法
1调用函数
public class Tester2 {
public static void main(String[] args) {
Calculator calculator=new Calculator();
calculator.div(1, 0);//提示除法运算被除数不能为0
}
}
2函数
public class Calculator {
public int div(int a,int b){
try {
return a/b;
} catch (ArithmeticException e) {//ArithmeticException异常
ArithmeticException1 arithmeticException1=new ArithmeticException1("除法运算被除数不能为0");
throw arithmeticException1;//抛出异常
}
}
}
3重新定义异常message
public class ArithmeticException1 extends RuntimeException{
private String message;//
public ArithmeticException1(String message) {
super();
this.message = message;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return this.message;
}
}
-- File:文件类
设计到文件,目录操作就需要用File类
-- 构造函数
要操作文件,第一步就是获取到一个文件对象
1,构造函数:File file=new file(指定一个文件路径);
作用:根据指定的虚拟路径创建了一个文件对象
2,判断文件是否存在:file.exists();
3,不存在的情况下,创建此文件对象
创建此文件;file.createNewFile()--使用这个函数去创建文件的时候一定要保证我呢间前面的目录都已经存在
创建此文件夹:file.mkdirs--路径里的一部分都会当做一个目录
注意:
file.mkdir();创建目录文件,一级目录
file.mkdirs();创建目录文件,多级目录
1
public class FileDemo {
public static void main(String[] args) throws IOException {
//throws IOException系统找不到指定的路径。
// String path="E:\\a.txt";//声明文件路径
String path="E:\\aa\\bb\\a.txt";//当路径不存在时,创建对象会抛IO错误
// String path="E:\\aa\\bb";//声明目录名
File file =new File(path);//创建file对象
// System.out.println("文件是否存在"+file.exists());
// if(!file.exists()){
// file.createNewFile();//创建文件
// file.mkdir();//创建目录文件,一级目录
file.mkdirs();//创建目录文件,多级目录
// System.out.println(file.exists());//判断文件是否存在
// }
// System.out.println(file.isDirectory());//判断目录是否存在
// File[]files=file.listFiles();//获取文件目录,创建文件数组
// System.out.println(files.length);//获取文件目录下的文件数量
// file.delete();//删除文件
}
}
2递归的用法,删除bb文件下面的文件和目录
public class FileDemo2 {
public static void main(String[] args) throws IOException {
String path="E:\\aa\\bb";
File file =new File(path);
digui(file);
}
private static void digui(File file) {
if(file.isFile()){
file.delete();
}else{
File[]files=file.listFiles();
for (File f : files) {
digui(f);//递归:自己调用自己
}
file.delete();
}
}
}
-- 判断文件、目录
对于系统上已经存在的文件,是可以判断他们的类型的
判断是否为文件:file.isFile()
判断是否为目录:file.isDirectory()
列出来一个目录下所有文件和子目录:file.listFiles()
删除文件:file.delete()
删除目录:file.delete()是不行的,必须用递归的方式去删除
递归:自己调用自己
-- IO流
概念:
IO流其实就是操作文件读写的一门技术
I:in(输入流,读取文件内容到流对象)
O:out(输出流,写文件内容到流对象)
分类
1,字节流-一般是操作图片,视频,音频文件的读写
2,字符流-一般是操作文本文件的读写
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
-- 文本类型字符流
public class BufferDemo {
public static void main(String[] args) {
String from="E:\\aa\\test.txt";//读地址
String to="E:\\aa\\bb\\test_copy.txt";//写地址
readAndWrite(from, to);//调用函数
}
static void readAndWrite(String from,String to){//文件内容拷贝的方法
File file=new File(from);
File file2=new File(to);
BufferedReader reader=null;
BufferedWriter writer=null;
if(file.exists()){
try {
reader =new BufferedReader(new FileReader(file));
writer =new BufferedWriter(new FileWriter(file2));
while(true){//while循环,当内容不为空写值,为空结束
String line=reader.readLine();
if(line!=null){//如果读取内容不为空
writer.write(line);
writer.newLine();//重新换行
}else{
break;
}
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(reader!=null){
reader.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(writer!=null){
writer.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
io流--字符流--reader-bufferedReader/fileReader
| |
| | -- writer-bufferedWriter/fileWriter
|
-- 字符流- InputStream-bufferedInputStream/FileInputStream
|
| -- OutputStream-bufferedOutInputStream/FileOutputStream
-- 36字节流
InputStream:输入流/写入流
OutputStream:输出流/写出流
InputStream和OutputStream都是抽象类,意味着这个抽象类中的
一些实现方法是可以被所有子类都共同调用的
FileInputSrream
read(byte[]bytes):将数组读到bytes数组,返回实际读取数据大小的size
FileOutputSrream
write(byte[]bytes,0,size):将数组里的数据写入到输出流,每次实际写的数据大小为上面读取的大小
例子
把方法封装出来的操作 先选中方法的代码-refactor-extract method
1调用方法ImageUtil.copyimage
public static void main(String[] args) throws FileNotFoundException {
String from="E:\\aa\\test.png";
String to ="E:\\aa\\bb\\test_cope.png";
ImageUtil.copyimage(from, to);
}
2读写的方法copyimage
public class ImageUtil {
public static void copyimage(String from, String to) {
File file1=new File(from);
File file2=new File(to);
if(file1.exists()){
FileInputStream ins =null;//创建读对象
FileOutputStream os =null;//创建写对象
try {
ins =new FileInputStream(file1);//创建读对象初始化
os =new FileOutputStream(file2);//创建写对象初始化
while(true){
byte[]bytes=new byte[1024];
int size=ins.read(bytes);//调用读的方法,返回读取数据大小
if(size==-1){
break;
}
os.write(bytes, 0, size);//调用写的方法,从0开始写
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(ins!=null&&os!=null){
try {
ins.close();
os.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}System.out.println("操作完毕");
}
}
ctrl+o快捷键,在当前类查找函数名