- 事实上没有对象变量这种东西。
- 只有引用到对象的变量。
- 对象引用变量保存的是存取对象的方法。
- 他不是对象的容器,而是类似指向对象的地址。或者可以说是地址。但是在Java中我们不会也不该知道应用变量中的实际装载的是什么,它只是用来代表单一的对象。只有Java虚拟机才会知道如何使用来用来取得该对象。
- Dog dog = new Dog
- 声明一个引用变量,要求Java虚拟机分配空间给引用变量,并将此变量命名为dog。此引用变量被永久固定为Dog类型。
- Dog dog = new Dog
- 创建对象,要求Java虚拟机分配给堆空间给新建的Dog对象。
- Dog dog = new Dog
- 连接对象和引用,将新定义的Dog赋值给dog这个引用能量。
- 数组也是对象。
- 一旦数组被声明出来,你就只能装入所声明类型的元素。
- 主数据类型的变量值是该值的字节所表示的。
- 局部变量没有默认值!如果在变量被初始前就要使用的话,编译器会显示错误
- ==比较的是两个数据是否引用的java.lang是个经常会用到的基础包,所以不用引用。
- public类型的成员变量会被继承。
- private类型的成员变量不会被继承。
- 重写规约:
- 参数必须要一样,且返回类型必须要兼容。
- 不能降低方法的存取权限。
- 重载:
- 返回类型可以不同。
- 不能只改变返回类型
- 可以更改存取权限
- 方法名要相同
- 抽象类除了被继承过之外,是没有用途、没有值、没有目的。
- 抽象方法必须被实现。
- 如果你声明出一个抽象方法,就必须将类也标记为抽象的。你不能在非抽象类中拥有抽象方法。
- 从ArrayList取出的Object都会被当做是 Object这个类的实例。编译器无法将此对象识别成Object以外的事务。
- 编译器是根据引用类型来判断有哪些方法可以调用的,而不是根据Object确定的类型。
- 所有接口的方法都是抽象的,所以任何实现接口的类,必须要实现这些方法。
- 接口的方法一定是抽象的,所以必须以分号结束。接口的方法没有内容。
- 类可以实现多个接口。
- 对象的生存空间是堆。
- 方法调用及变量的生存空间是栈。
- 当Java虚拟机启动时,它会从底层的操作系统取得一块内存,并以此区段来执行Java程序。
- 局部变量又称栈变量,局部变量和方法参数都是被声明在方法中。它们是暂时的,且生命周期只限于方法被放在栈上的这段期间,也就是方法调用至执行完毕为止。
- 实例变量是声明在类中方法外的。它代表每个独立对象的字段,每个实例都能有不同的值,实例变量存在于所属的对象中。
- 当你调用一个方法时,改该方法会放在调用栈的栈顶。实际上被堆上栈的是堆栈快,它带有方法的状就算你没有写构造函数,编译器也会帮你写一个。构造函数一定要与类名相同。
- 构造函数有一个关键的特征,它会在对象能够被赋值给引用之前就执行。
- 使用构造函数可以初始化对象的状态。
- 如果你已经写了一个有参数的构造函数,并且你需要一个 没有参数的构造函数,这个时候需要手动写一个,编译器不会自动生成。
- 如果类上有一个以上的构造函数,则参数一定要不一样。
- 如果实例变量是个对对象的引用,则引用与对象都是在堆上。
- 实例变量有默认值,原始的默认值是0/0.0/false。
- 在创建新的对象时,所有继承下来的构造函数都会执行。
- 新建一个子类,会执行子类与父类的构造函数,先执行父类的,再执行子类的。
- 如果你没有在子类中编写构造函数,那么编译器会给我们加上构造函数,并在函数里调用super(),如果子类中编写了构造函数,但是没有在构造函数里编写super(),那么编译器会在我们的构造函数里加上super()。
- 每个构造函数可以选择调用super()或者this(),但不能同时调用。
- 使用this()从某个构造函数调用同一个类的另外一个 构造函数。
- this()只能用在构造函数中,且必须是第一行语句。态,包括执行到哪一行程序以及所有的局部变量的值。同一个对象,比较的是地址值。

关于构造器重载方面,
构造器像一般方法一样,也可以重载。
例如:
public class Test {
public static void main(String[] args) {
Person person1 = new Person();//使用无参的构造器初始化
Person person2 = new Person("张三");//使用一个名字参数的构造器初始化
Person person3 = new Person("李四", 19);//使用两个参数的构造器初始化
}
}
class Person {
String name;
int age;
//无参构造器
public Person() {
this.name = "无名";
this.age = 18;
}
//一个名字参数的构造器
public Person(String name) {
this.name = name;
this.age = 18;
}
//两个参数的构造器
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
重载的规则与一般方法的规则也是一致的。
补充一下细节:
1.构造器只完成对对象的初始化
构造器只完成对象的初始化,不会创建对象。
2.查看默认的构造器
上面我们说到,如果没有显示自定义构造器,Java编译器会自动提供一个无参的默认构造器。我们可以使用 javap 反编译查看这个构造器:
以下列代码为例,这里定义一个类,里面没有任何内容:
class Cat {
}
然后我们使用 javac 指令进行编译,
然后使用 javap 反编译字节码文件,得到的内容如下:
我们可以看到这里是对应的一个方法的声明
构造器的继承
定义父类构造器,覆盖了默认的无参构造器,不能直接 new Father() 调用了,除非再定义一个无参构造器
//父类构造器
public class Father{
//自定义带参构造器
public Father(String str){
System.out.println("父类的带参构造方法,参数为:"+str);
}
}
定义子类构造器,继承Father,由于Father没有无参构造器,所以必须在子类构造器中通过 super(“字符串”)来调用,否则编译器会报错
//子类构造器
public class Son extends Father{
//无参构造器
public Son(){
//由于Father()没有无参构造器,所以必须在子类型构造器中通过super("字符串")来调用,否则编译器会报错。
//如果没定义这句,系统会默认调用super()
super("");
}
//带参构造器
public Son(String str){
//由于Father()没有无参构造器,所以必须在子类型构造器中通过super("字符串")来调用,否则编译器会报错。
//如果没定义这句,系统会默认调用super()
super(str);
}
}
构造器、静态代码块、构造代码块的执行顺序
无继承的情况
public class Father {
static {
System.out.println("父类的静态代码块,程序启动后执行,只会执行一次");
}
//父类无参构造方法
public Father(){
System.out.println("父类的默认构造方法");
}
//重载,自定义父类带参构造方法
public Father(String str){
System.out.println("父类的带参构造方法,参数为:"+str);
}
{
System.out.println("父类构造代码块,每次调用构造方法都会执行的");
}
}
实例化Father
//实例化Father
public static void main(String[] args) {
System.out.println("---------------------------------------");
Father father1 = new Father();
System.out.println("---------------------------------------");
Father father2 = new Father("阿马");
}
执行上述代码
父类的静态代码块,程序启动后执行,只会执行一次
父类构造代码块,每次调用构造方法都会执行的
父类的默认构造方法
--------------------------------------
有继承的情况
定义父类Father
public class Father {
static {
System.out.println("父类的静态代码块,程序启动后执行,只会执行一次");
}
//父类无参构造方法
public Father(){
System.out.println("父类的默认构造方法");
}
//重载,自定义父类带参构造方法
public Father(String str){
System.out.println("父类的带参构造方法,参数为:"+str);
}
{
System.out.println("父类构造代码块,每次调用构造方法都会执行的");
}
}
定义子类Son,继承自父类Father
//子类构造器
public class Son extends Father{
static {
System.out.println("子类的静态代码块,程序启动后执行,只会执行一次,先执行父类的,在执行子类的");
}
{
System.out.println("子类构造代码块,每次调用构造方法都会执行的");
}
//无参构造器
public Son(){
//这里没有指定调用父类的哪个构造方法,会默认调用super(),调用父类的无参构造器public Father()
}
//重载构造器,多传两个参数
public Son(String str1,String str2){
//必须写在构造器第一行,调用父类的带参构造器public Father(str)
super(str1);
System.out.println("子类带参构造器:"+str2);
}
}
异常处理(整理)
- Java中的所有异常都来⾃顶级⽗类Throwable,Throwable下有两个⼦类Exception和Error。
- Throwable类,是所有异常类的根类,Java异常的顶层父类,所有的异常类都是由它继承。
- Exception:异常,程序本身可以处理的异常。
- Java中异常继承的根类是:Throwable。Throwable是根类,不是异常类。
- Exception才是异常类,当程序出现Exception时,是可以靠程序⾃⼰来解决的,它才是开发中代码在编译或者执行的过程中可能出现的错误,它是需要提前处理的,以便程序更健壮!
- 异常体系的最上层父类是Exception。
- Exception的⼦类通常⼜可以分为RuntimeException和⾮RuntimeException两类
- 异常分为两类:编译时异常(受检异常,必须处理)、运行时异常(非受检异常)。
- 受检异常:就是程序必须手动处理的异常,如果不手动处理,则会编译失败。
- 非受检异常:不强制程序处理的异常,不强制你手动处理,无需try...catch...,也无需throws,代码也能编译成功。
- Error也属于非受检异常。
- 编译时异常{受检异常-Checked Exception}:没有继承RuntimeException的异常,直接继承于Exception。编译阶段就会错误提示 / 报错,必须要手动处理(如果受检查异常没有被 catch或者throws 关键字处理的话,就没办法通过编译),否则代码报错不通过。编译时异常是为了提醒程序员,比如:IOException、ClassNotFoundException、ParseException、SQLException、java.io.FileNotFoundException...
- 运行时异常{非受检异常-Unchecked Exception}:继承了RuntimeException,RuntimeException本身和子类。编译阶段不会报错 / 出现异常提醒,运行时出现的异常。运行时异常是代码出错而导致程序出现的问题。
一.Throwable体系:
a.Error:严重错误Error,无法通过处理的错误,只能事先避免,好比绝症。
b.Exception:表示异常,异常产生后程序员可以通过代码的方式纠正,使程序继续运行,是必须要处理的。好比感冒、阑尾炎。
Throwable中的常用方法:
a.public void printStackTrace():打印异常详细信息。
b.public String getMessage():获取发生异常的原因。
c.public String toString():获取异常的类型和异常描述信息(不用)。
二.异常分类
我们平常说的异常就是指Exception,因为这类异常一旦出现,我们就要对代码进行更正,修复程序。
异常(Exception)的分类:
a.编译时期异常:checked异常。在编译时期,就会检查,如果没有处理异常,则编译失败。(如日期格式化异常)。
b.运行时期异常:runtime异常。在运行时期,检查异常.在编译时期,运行异常不会编译器检测(不报错)。(如数学异常)。
三、异常的处理
Java异常处理的五个关键字:try、catch、finally、throw、throws 。。
1.抛出异常throw
在编写程序时,我们必须要考虑程序出现问题的情况。比如,在定义方法时,方法需要接受参数。那么,当调用方法使用接受到的参数时,首先需要先对参数数据进行合法的判断,数据若不合法,就应该告诉调用者,传递合法的数据进来。这时需要使用抛出异常的方式来告诉调用者。
在java中,提供了一个throw关键字,它用来抛出一个指定的异常对象。
a.创建一个异常对象。
b.需要将这个异常对象告知给调用者。
throw用在方法内,用来抛出一个异常对象,将这个异常对象传递到调用者处,并结束当前方法的执行。
使用格式:
thr例如:
throw new NullPointerException("要访问的arr数组不存在");
throw new ArrayIndexOutOfBoundsException("该索引在数组中不存在,已超出范围");
public class Test {
public static void main(String[] args) {
//创建一个数组
int[] arr = {2,4,52,2};
//根据索引找对应的元素
int index = 4;
int element = getElement(arr, index);
System.out.println(element);
System.out.println("over");
}
/*
* 根据 索引找到数组中对应的元素
*/
public static int getElement(int[] arr,int index){
//判断索引是否越界
if(index<0 || index>arr.length-1){
throw new ArrayIndexOutOfBoundsException("角标越界了~~~");
}
int element = arr[index];
return element;
}
}
tips:如果产生了问题,我们就会throw将问题.声明异常throws
声明异常:将问题标识出来,报告给调用者。如果方法内通过throw抛出了编译时异常,而没有捕获处理(稍后讲解该方式),那么必须通过throws进行声明,让调用者去处理。
关键字throws运用于方法声明上面,意思是当前方法不处理异常,来提醒该方法的调用者来处理异常(抛出异常)。
声明异常格式:
修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2…{ }
声明异常的代码演示:
public class Test {
public static void main(String[] args) throws FileNotFoundException {
read("a.txt");
}
// 如果定义功能时有问题发生需要报告给调用者。可以通过在方法上使用throws关键字进行声明
public static void read(String path) throws FileNotFoundException {
if (!path.equals("a.txt")) {//如果不是 a.txt这个文件
throw new FileNotFoundException("文件不存在");
}
}
}
throws用于进行异常类的声明,若该方法可能有多种异常情况产生,那么在throws后面可以写多个异常类,用逗号隔开。
public class Test {
public static void main(String[] args) throws IOException {
read("a.txt");
}
public static void read(String path)throws FileNotFoundException, IOException {
if (!path.equals("a.txt")) {//如果不是 a.txt这个文件
throw new FileNotFoundException("文件不存在");
}
if (!path.equals("b.txt")) {
throw new IOException();
}
}
}
描述类即异常进行抛出,也就是将问题返回给该方法的调用者。 ow new 异常类名(参数);
36万+

被折叠的 条评论
为什么被折叠?



