JavaSE-异常
异常 概述 异常是指程序在执行过程中出现的非正常情况,如果不处理最终会导致JVM的非正常停止 异常的抛出机制:Java把不同异常用不同的类表示,一旦发生某种异常,就创建该异常类型的对象,并且抛出(throw)。然后程序员可以捕获(catch)到这个异常现象,并处理;如果没有捕获这个异常对象,那么这个异常对象会导致程序的终止。 常见异常 Error:StackOverflowError、OOM Exception: 编译时异常(受检异常)在执行javac.exe时出现的异常: ClassNotFoundException FileNotFoundException IOException 运行时异常(非受检异常)在执行java.exe时出现的异常: ArrayIndexOutOfBoundsException NullPointerException ClassCastException NumberFormatException InputMismatchException ArithmeticException 异常处理 方式一:try-catch-finally 基本结构: 12345678910try{ ......//可能产生异常的代码}catch(异常类型1 e){ ......//当产生异常类型1时的处置措施}catch(异常类型1 e){ ......//当产生异常类型2时的处置措施}finally{ ......//无论是否异常都会执行} 使用细节: 如果声明多个异常类型且存在子父类关系,则子类异常要写在上面。否则无关上下。 catch中异常处理的方式: 自己编写输出的语句 printStackTrace():打印异常的详细信息 getMessage():获取发生异常的原因 try中声明的结构,除了try结构后就不可以再调用了 将一定要被执行的代码写在finally 无论try中或catch中是否存在仍未被处理的异常,无论try中或catch中是否存在return,都会执行。唯一的例外:System.exit(0)会强行终止当前运行的VM 在开发中,有一些资源(输入流、输出流、数据库连接、Sokect),在使用完后,必须显式地进行关闭,否则会导致内存泄漏。 方式二:throws+异常类型 格式:public void test() throws 异常类型1,异常类型2,.....{//可能存在编译时异常的代码} throws处理异常的方式,仅是将可能出现的异常抛给了此方法的调用者。调用者仍要考虑如何处理异常。 方法重写的要求:(针对编译时异常) **(重要)**子类抛出的异常类型要么和父类异常类型一样,要么是父类异常类型的子类。 throws和try-catch-finally的选择: 如果程序代码中,涉及到资源的调用(流、数据库连接、网络连接等),则必须考虑使用try-catch-finally来处理,保证不出现内存泄漏。 如果父类被重写的方法没有throws异常类型,则子类重写的方法中如果出现异常,只能考虑使用try-catch-finally进行处理,不能throws。 开发中,方法a中依次调用了方法b,c,d等方法,方法b,c,d之间是递进关系。此时,如果方法b,c,d中有异常,我们通常选择使用throws,而方法a中通常选择使用try-catch-finally。 抛出异常对象 异常的处理过程中有两个过程,一个是“抛”,一个是“抓“ “抛”的过程在程序上就是产生异常对象的过程,具体又可以分为自动抛和手动抛,这里的throw就是手动抛的过程 “抓”的过程实际上就是处理异常的过程,上述的throws和try-catch-finally就是处理异常的过程。 throw的使用:写在方法里,格式是throw 异常对象,这样就可以产生一个异常对象。 例子: 123456try{ throw new Exception("手动抛出异常");//创建一个名为手动抛出异常的异常对象}catch (Exception e) { System.out.println("捕获异常"); ...
面向对象(高级)
面向对象高级 static关键字 static用来修饰的结构:属性、方法;代码块、内部类 我们可以按照变量在类中声明的位置,分为局部变量和成员变量。对于成员变量又可以进一步分类: 对于加了static关键字的变量,我们称为静态变量、类变量; 对于没有加static关键字的变量,我们称为实例变量、非静态变量。 静态变量和实例变量对比 静态变量 实例变量 个数 只有一份,被类的多个对象共享 每一个对象都保存有一份 内存位置 jdk6及之前,在方法区,jdk7及之后再堆 存放在堆空间的对象实体中 生命周期 随类的加载而加载,随类的卸载而消亡 随对象的创建而加载,随对象的消亡儿消亡 调用者 可被类直接调用,也可被对象调用 只能被对象调用 static修饰方法 随着类的加载而加载 可以通过“类.静态方法”的方式,直接调用静态方法 静态方法内可以调用静态的属性或静态的方法,不可以调用非静态的结构(比如属性和方法) 静态方法可被类直接调用,也可被对象调用;实例方法只能被对象调用 静态方法内不能用this和super(理解:因为静态方法随类的加载而加载,而this和super都是需要产生对象才可以使用的,但是VM是先加载类再加载对象,所以静态方法使用this和super显然是不合适的) 什么时候要使用static? 属性:1)当前类的对象是否能共享此属性,且此变量值相同。2)常量 方法:方法内操作的变量都是静态变量。工具类的方法,如:Arrays、Maths 单例(Singleton)设计模式 饿汉式 1234567891011class Bank{ private Bank(){//1.私有化构造器 } //2.创建实例 //4.声明为static private static Bank instace = new Bank(); //3.获取实例 public static Bank getInstance(){ return instance; }} “立即加载”,随着类的加载就创建了 优点:写法简单,运行较快,是线程安全的 缺点:内存占用时间长 懒汉式 1234567891011121314class GirlFriend{ private Bank(){//1.私有化构造器 } //2.声明实例 //4.声明为static private static Bank instace =null; //3.获取实例,如果没有创建对象,则在方法内再创建 public static Bank getInstance(){ if(instance == null){ instance=new Bank(); } return instance; } } “延迟加载”,在需要的时候才创建对象 优点:节省内存 缺点:线程不安全 类的成员之四:代码块 代码块,也叫初始化块。是用来初始化类或对象的信息。按照是否加static修饰分为静态代码块和非静态代码块。静态代码块随着类的加载而执行,由于类的加载只会执行一次,所以静态代码块只会执行一次;非静态代码块随着对象的创建而执行,没创建一个实例,都会执行一次。静态代码块要先于非静态代码块执行。 作用:可以把不同构造器中相同的部分写在代码块中进行赋值;对静态变量进行赋值。 例子: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354public class UserTest2 { public static void main(String[] args) { User2 user1 = new User2(); System.out.println(user1.getInfo()); System.out.println("===================================="); User2 user2 = new User2("KuoZ", "80841007"); ...
面向对象(进阶)
面向对象(进阶) this关键字 this可以调用:属性、方法;构造器 this调用属性和方法 this 理解为当前对象,也就是说代表调用属性或方法的对象. this 通常可以省略,但是在属性的名称和形参变量的名称一样的情况下,就必须用this. 标示出成员变量。方法里通常省略this 。 this调用构造器 使用this(形参列表) 调用当前类中其它的重载的构造器,this(形参列表) 必须声明在当前构造器的首行,所以在一个构造器最多出现一次。 理解:在类中有n个构造器,则最多有n-1个this(形参列表) 结构 面向对象特征之二:继承性 继承的基本概念 继承性的好处: 减少代码冗余,提高复用性 便于功能扩展 产生了is-a的关系,为多态的使用提供了前提 继承性的特点 单继承性:但是一个子类只能有一个父类。 Java支持多层继承,一个父类可以扩展为多个子类。 Java中声明的类,如果没有显式声明其父类,默认继承于java.lang.Object类。 Java中子类父类的概念是相对的。 继承的格式 1234567class A{}class B extends A{} 上边代码中: A类:父类、superClass、超类、基类 B类:子类、subClass、派生类 继承的作用 通过这样声明,子类能够获得了父类声明的所有属性和方法。 子类继承父类后,还可以扩展自己的功能,要区别于集合和子集的概念。 同时,继承不打破封装性,所以因为封装性,子类不能直接调用父类私有的属性。但可以通过get方法调用。 方法的重写(overwrite/override) 子类对从父类继承过来的方法进行的覆盖、覆写的操作,称为重写(overwrite) 方法重写的规则: 父类被重写的方法的方法名和形参列表必须相同 子类重写的权限修饰符不小于父类的修饰符。特例:子类不能重写父类中private的方法 返回值类型: 父类为void,则子类重写只能是void 父类返回为基本数据类型,则子类同类型 父类返回为引用数据类型,则子类重写的方法的返回值类型相同 或 是引用数据类型的子类 关于异常类型,子类重写的方法抛出的异常类型可以和父类被重写的方法抛出的异常类型相同,也可以是其子类 super关键字 使用场景:在子类中已经对父类中的方法进行了重写,但是又想要调用父类的方法,这是就要用super关键字 子类与父类定义了同名的属性,使用super可以区分子类和父类的属性。 super可以调用属性、方法;构造器 super调用属性、方法 子类继承父类以后,可以在子类的方法或构造器中调用父类的属性和方法。在满足封装性的前提下,使用super. 表示父类的属性或方法。 一般情况下,我们可以考虑省略super. ,但是如果子类中声明了同名的属性或者重写了父类的方法,就必须用super. 表示父类的属性和方法。对于子类父类的属性要尽量避开重名的情况(编程规范),而方法可能无法避免,就可以用super. 来调用 super调用构造器 子类继承父类时是不会继承构造器的,可以在子类构造器中用super(形参列表) 调用父类的构造器。 规定super(形参列表) 必须写在子类构造器的首行,这也就意味着this和super只能出现一个。 如果没有写super(形参列表) 或this(形参列表) ,则默认是super() 。 由2、3得出结论,子类的任何一个构造器要么调用本类中重载的构造器,要么调用父类中的构造器。 由4得到,一个类中声明有n个构造器,最多有n-1个构造器使用了this(形参列表) ,剩下那一个一定使用super(形参列表) 。–>在调用子类的构造器时,一定直接或间接调用了父类的构造器,也正因为调用了父类的构造器,我们才会将父类中声明的方法或属性加载到内存中,供子类对象使用。 子类对象实例化的全过程: 从结果来看,体现为类的继承性。 从过程上来讲,当我们通过子类的构造器创建对象时,一定会直接或间接得调用到其父类的构造器,父类也会直接或间接调用其父类的构造器……直到调用了Object类的构造器为止。 面向对象特征之三:多态性 基本概念 多态性使用的前提:1.要用子类的继承关系 2.要有方法的重写 如何理解多态性? 广义上:子类对象的多态性、方法的重写 狭义上:主要指子类对象的多态性 Java中多态性主要体现在子类对象的多态性:子类的对象赋给父类的引用。 例Object obj = new String("hello");其中String()是子类的构造器,而Person是String的父类。 多态的优劣: 优点:1....
面向对象(基础)
面向对象(基础) 序言 面向对象的三条主线: 类及类的成员:属性、方法、构造器;代码块、内部类 特征:封装性、继承性、多态性 其他关键字:static、package、import 概述 对比面向对象和面向过程 POP(Procedure Oriented Programming)以函数为单位,是一种执行者的思维 OOP(Object Oriented Programming)以类为单位,是一种设计者的思维 面向对象编程的两个核心概念:类(Class)和对象(Object),类是具有相同特征的集合,是抽象的;对象是实际存在的该类事物的个体,是具体的。 面向对象完成具体功能的操作流程: 创建类,设计类的成员; 创建对象; 通过对象,调用其内部声明的属性或方法,完成相关功能。 类的使用参考代码: 1234567891011121314151617public class PersonTest {//测试类 public static void main(String[] args) { Person p1= new Person();//创建对象 p1.name="Miku";//通过对象,调用其内部声明的属性或方法 p1.id=233; p1.age=14; p1.gender='女'; System.out.println("姓名:"+p1.name+"标号:"+p1.id+"年龄: "+p1.age+"性别: "+p1.gender); }}class Person{//创建类,设计类的成员; String name; int id; int age; char gender;}//运行结果: 姓名:Miku标号:233年龄: 14性别: 女 类中对象的内存解析 Java中内存结构的划分:虚拟机栈、堆、方法区;程序计数器、本地方法栈 虚拟机栈:以栈帧为基本单位;入栈对应方法的执行;方法的局部变量会存储在栈帧中 堆空间:new出来的结构(数组、对象)1.数组的元素2.对象的成员变量。 方法区:加载的类的模板结构。 参考一段代码: 1234567Person p1= new Person();p1.age=12;class Person{//创建类 String name; int id; int age;} 在内存上,使用new之后,会在堆里创建一段空间用于存储name、id、age,而p1在栈中存储这段空间的首地址。之后对p1.age进行赋值,是在堆中改变了age的值。 可以总结出引用数据类型存储的其实都是地址 类的成员之一:属性 变量可以按类型分类也可以按照声明位置分类,按位置可以分为成员变量和局部变量。 属性的别名:成员变量、field(字段、域) 成员变量和局部变量对比 位置不同 内存分配不同:局部变量保存在栈、成员变量保存在堆 生命周期: 成员变量随对象产生随对象消亡,局部变量在栈帧中分配,随方法出栈消亡 成员变量可用权限修饰符修饰,局部变量不行 默认值:局部变量没有默认初始化值,属性都有其默认初始化值 类的成员之二:方法 Java的方法不能独立存在,必须定义在类里 方法的声明格式: 权限修饰符 + [其他修饰符] + 返回值类型 + 方法名(形参列表)[throws 异常类型]{//方法头 //方法体 } 调用本类方法:方法可以调用本类其他方法,也可以调用自己(递归) return的使用: 结束方法 将结果返回给其调用者 形参和实参 形参:定义方法时,声明的变量成为形参 实参:调用时实际传给形参的变量/常量/表达式 再谈方法 方法是设计类的核心,能否实现功能主要看方法。下面就重载、可变个数形参、值传递机制、迭代等方法的应用再进行补充说明。 重载(overload) 重载是指同一个类中两个方法名相同的情况,要讨论的核心其实是Java编译其辨别不同方法的机制 是否为不同方法仅与方法名和形参列表有关 注:形参列表不同只与形参的类型有关,而与其名称无关。相应的,类型相同,顺序不同也是两个方法。 关于自动类型提升,编译方面会能不自动提升就不自动提升。 可变个数形参(jdk5.0的新特性) 场景:形参类型确定,个数不确定 格式:(类型 ......
Java基本语法
0.简单的DOS命令 md(生成文件),cd(跳转路径),rd(del)(删除文件),dir(显示文件目录) 1.JAVA程序基本结构 JAVA执行的基本流程: 编写.java文件,之后由javac.exe文件生成字节码文件(.class),再由java.exe运行。 简单的HelloWorld程序: 12345class HelloChina{ public static void main(String[] args){ System.out.println("Angel Beats!"); }} 在class内部,可以定义若干方法(method)。 关于命名 JAVA严格区分大小写,而Windows不区分大小写。 类名要求: 类名必须以英文字母开头,后接字母,数字和下划线的组合 习惯以大写字母开头,使用驼峰命名 方法名、变量名: 和类名一样,不过首字母要小写,使用小驼峰命名 关于注释 JAVA特有:文档注释 1234/*** look in my eyes!* @KuoZ*/ 练习题 1.为什么JAVA是半编译半解释型语言? 2.内存泄漏和内存溢出是什么,JAVA还会发生这些问题吗?能否举一个例子? 3.一个JAVA文件里能否声明多个类,有什么限制? 2.变量和运算符 关键字和标识符 JAVA里一共有50个关键字。false和true可以当做关键字来看待。 还有goto和const两个保留字 可以自己起名的都是标识符,包括类名、方法名、变量名、接口名等。 变量 JAVA中变量的两种类型 基本数据类型 整型 byte short int long 浮点型 float double 字符型 char 布尔型 boolean 引用数据类型(先记录三类) 类 数组 接口 基本数据类型 整型 分别占1、2、4、8个字节。与c语言不同,JAVA只定义了带符号的整型。long型结尾需要加L/l。不加则为int类型,但是int类型可以赋值给long型,可以正常运行。 浮点型 分别占用4、8字节。对于float类型,需要加上f后缀,否则默认为double类型。 ps:十进制小数和二进制小数并不能一一对应,二进制小数不能准确表示0.1、0.01……这些10的负次幂的数。所以说对于语句System.out.println(0.1+0.2);输出的结果不等于0.3。 字符型 占两个字节,JAVA的char类型除了用ASCII码外,还可以用Unicode码赋值。综合下来可以有四种形式对char型赋值 char name = '中' 用一对单引号括起来进行赋值,单引号内有且仅有一个字符 char name='\u0036'单引号内是\u+相应的Unicode码 char name='\n'单引号内是转义字符 char name=51直接用ASCII码对字符进行幅值 布尔型 布尔型只有true和false两种取值,且不能用1、0代替。在编译时不谈boolean型的占用字节,在内存分配上,实际上占用4个字节。 1ps:JVM的内存分配问题:小于4个字节的分配1个slot(slot,槽位,等于4个字节),大于四个字节的分配2个slot。 var关键字 使用var时,会自动根据赋值语句来判断变量类型,实际上也就是省了写变量类型。 注意:var关键字在JAVA10之后才有。 常量 使用final表示常量类型,如final int AGE = 20 。常量的命名应全大写,使用常量以避免被人诟病”MagicNumber”。 作用域(scope) 定义作用域时,要遵循作用域最小原则,尽量少定义全局变量,也不要重复使用变量名。 基本数据类型变量运算规则 对于变量之间运算问题,变量的类型问题尤为重要。 除布尔型的其他7种基本数据类型可以参与运算,运算时候的变量类型问题如下: 自动类型提升 自动类型提升用于将容量小的变量类型自动提升为容量大的类型(ps:容量指的是表示数的范围大小而非所占内存大小) 结论: graph LR A[byte]==>B[int] C[short]==>B D[char]==>B B==>E[long] E==>F[float] F==>G[double] 整型常量默认为int型,浮点型默认为double型。byte、short、char之间运算结果为int型。 强制类型转换 强制类型转换用于将变量强制转换为指定类型。使用“( )“,”(...
主题~
一点牢骚 我自己的博客网站基本配置好了,选了张涩涩的miku当头图,或许这样能让我写代码和文的时候肾上腺素提升从而提高效率呢(bushi)。 好像很多技术党都有一个自己博客,我也就东施效颦一下,但是其实更多的原因还是因为他人,也就是跟风。一直以来,我好像都缺乏一个内源的动力和目标,也没有什么自己的想法和意志,一直都是在不停地模仿。但是那又如何呢? 我真的很讨厌自己去做选择,既没有能做出正确决定的视野,连做出决定的决心也没有。算了,我也不想过分自贬,就这样吧。 言归正传,用了一天半搭建的网站还是可以庆祝一下的,也是有了一个个人的空间,或许可以成为我之后若干年还活着的证明。 整体来讲,我想写一个是学习笔记,专业的技术文我也没有写的实力,还有就是一个经验积累,最后就是一些随想,当日记写呗就。 最后附一张可爱的公主殿下!(typora的图片直接插入功能太好用了)