类与对象的区别和联系
{
- 类代表一类事物
- 对象代表一个具体事物
- 类是对象的模板,对象是类的一个个体
(有点像C中的结构体)
}
属性(成员变量)
属性是可以是基本数据类型,也可以是医用类型(对象,数组)
如何创建对象
{
- 先声明,再创建
Cat cat;
cat = new Cat(); - 直接创建
Cat cat = new Cat();
}
如何访问属性
{
对象名.属性名
}
---->java中易出现的错误:空指针异常///
方法
1、一个方法最多有一个返回值(问:如何返回多个结果???)
答:返回数组!!
例:public int[] getSumAndSub(int n1,int n2){
int [] array = new int [2];
array[0] = n1+n2;
array[1] = n1-n2;
return array;
}
方法重载(方法名一致,形参不一样,参数名无要求,返回类型无要求)
例如:System.out.println();其中out是一个类,println是方法名;
*可变参数
细节:
(用于:方法名相同,功能相同,参数个数不同)
(可变参数的实参可以是数组(可变参数的本质就是数组))
(可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数放在最后)
(一个形参列表最多可以出现一个可变参数)
public int sum ( int… nums ){ (其中nums可当做数组来看)
System.out.println("接受参数个数是"+nums.length());
int res=0;
for(int i=0;i<nums.length();i++){
res +=nums[i];
}
return res;
}
作用域:全局变量,局部变量的使用范围。
PS:全局变量可以不赋值直接使用(因为系统自动分配默认值),而局部变量必须赋值后才能使用。
PS:成员变量可以不赋值,有默认初始值。
注意事项及细节:
1、(方法的)属性和局部变量可以重名,访问时就近原则。
2、全局变量/属性 可以加修饰符,局部变量不可以加修饰符
封装
继承
继承总结
- 子类继承了所有(包括私有!!!)的属性和方法,但私有属性和方法不能在子类直接访问,可在父类中创建public方法来返回私有属性(这样,子类就会继承该方法,从而得到父类私有属性)。
- 子类必须调用父类的构造器,完成父类的初始化。
- 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有无参构造器,则必须在子类的构造器中用super去指定使用父类的哪个有参构造器完成对父类的初始化工作,否则编译不会通过。
PS:(父类若有有参构造器,则无参构造器就不会默认存在;若父类无任何构造器,则会存在一个默认无参构造器)
PS:(父类的构造器一定在子类构造器的第一行(先于子类构造))
- 如果希望指定去调用父类的某个构造器,则显式地调用一下:super(参数列表)。
- supper()在使用时,必须放在构造器的第一行。
- super()和this()都智能放在构造器第一行,因此这两个方法不能共存在一个构造器。
- Java所有类都是Object类的子类,Object是所有类的基类。
- 父类构造器的调用不限于直接父类!将一直往上追溯到Object类。
- 子类最多只能继承一个父类(Java单继承机制)
- 不能滥用继承,子类和父类之间必须满足is-a的逻辑关系。
继承详解
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
Son son = new Son();
//–>这时注意,要按查找关系来返回信息
//(1)首先看子类是否有这个属性
//(2)如果子类有这个属性,并且可以访问,则返回信息(就近原则)
//(3)如果子类没有这个属性,就看父类有没有这个属性(如果有,并且可以访问,则返回信息)(PS:如果有该属性,但是private,则不会往上找了,直接报错)
//(4)如果父类没有就按(3)的规则继续寻找上级父类,直到Object
System.out.println(son.name);//返回儿子
System.out.println(son.age);//返回45
System.out.println(son.hobby);//返回旅游
in.close();
}
}
class GrandPa{//爷爷类
String name = “爷爷”;
String hobby = “旅游”;
}
class Father extends GrandPa{//父类
String name = “父亲”;
int age=45;
}
class Son extends Father{//子类
String name = “儿子”;
}
super关键字
基本介绍:super代表父类的引用,用于访问父类的属性、方法、构造器
多态
基本介绍:方法和对象具有多种形态。作为面向对象的第三大特征,多态建立在封装和继承基础之上。
多态的体现:
1、方法的多态:重写和重载体现多态
2、对象的多态
(1)一个对象的编译类型和运行类型可以不一致
例:Animal animal = new Dog(); ------->animal的编译类型是Animal,运行类型是Dog
animal = new Cat();------------>animal的运行类型变成了Cat,编译类型仍是Animal;
(2)编译对象在定义对象时就确定了,不能改变
(3)运行类型是可以变化的
(4)编译类型看定义时=号的左边,运行类型看=号右边
多态细节及注意事项
(一)向上转型及向下转型
1、本质:向上转型:父类的引用指向了子类的对象(例:Animal animal = new Dog(); 父类Animal->子类Dog)
2、语法:父类类型 引用名 = new 子类类型();
3、特点:编译类型看左边,运行类型看右边
可以调用父类中!所有成员!(需遵循访问权限)
!不能!调用子类中 !特有成员!(因为在编译阶段,能调用哪些成员(属性、方法)由编译类型决定)
最终运行效果看子类的具体实现,即调用方法是,按照从子类开始查找方法,若子类父类共有一个方法,优先子类(方法重写)
/!!!!!!!!!!!!!!!!!非常重要!!!!!!!!!!!!!!!!
多态的向下转型(解决如何调用子类特有成员的问题)
1、语法:子类类型 引用名 = (子类类型) 父类引用(例:Dog dog = (Dog) animal; )
2、只能强转父类的引用,不能强转父类的对象
3、要求父类的引用必须指向的是当前目标类型的对象
4、当向下转型后,可以调用子类类型中所有的成员
(二)属性重写问题
1、属性没有重写之说,属性的值看编译类型
2、instanceOf 比较操作符,用于判断对象的 运行类型 是否为XX类型或XX类型的子类型
/
多态之动态绑定
1、当调用对象方法时,该方法会和该对象的内存地址(运行机制)绑定
2、属性没有动态绑定机制(就近原则),哪里声明,哪里使用(返回return时的类的返回的属性)
抽象类
1、用abstract关键字来修饰一个类时,这个类就叫抽象类
2、用abstract关键字来修饰一个方法时,这个方法就叫抽象方法
3、抽象类的价值更多作用是在于设计,是设计者设计好后,让子类继承并实现抽象类()
抽象类细节
- 抽象类不能被实例化—>public abstract void hi();
- 抽象类不一定要包含abstract方法,也就是说,抽象类可以没有abstract方法
- 一旦类包含了abstract方法,则这个类必须声明为abstract
- abstract只能修饰类和方法
- 抽象类可以有任意成员【本质还是类】,比如:非抽象方法,构造器,静态属性…
- 抽象方法不能有主体------->abstract void hi () {};(×)
- 如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法,除非它自己也声明为抽象类
- 抽象方法不能使用private,final,static来修饰,因为这些关键字都是和重写相违背的
接口
基本介绍:接口就是给出一些没有实现的方法(抽象方法),封装到一起,到某个类要使用时,在根据具体情况把这些方法写出来。PS:JDK8以后,也可以有已实现的方法、静态方法,不过要加default(默认)
语法:interface 接口名{
属性
方法
}
class 类名 implements 接口{
自己属性
自己方法
必须实现接口的抽象方法
}
异常处理
程序
try{
代码可能有异常
}catch (Exception ex){
//捕获到异常
//1、当异常发生时
//2、系统将异常封装成Exception对象ex , 传递给catch
//3、得到异常对象后,程序员,自己处理
//4、注意,如果没有发生异常,catch代码块不执行
}finally{
//1、不管try代码块是否有异常发生,始终要执行finally(也可以不写finally)
//2、所以,通常将释放资源的代码,放在finally
}
Java提供try和catch块来处理异常。try块用于包含可能出错的代码。catch块用于处理try块中发生的异常。
可以根据需要,在程序中有多个try…catch块。
异常处理细节及注意事项
1、如果异常发生了,则异常发生后面的代码不会执行,直接进入到catch块
2、如果异常没有发生,则顺序执行try块,不会进入到catch
3、如果希望不管是否发生异常,都执行某段代码,则使用finally{}
4、如果有多个catch语句,捕获不同的异常,要求父类异常在后,子类异常在前(比如Exception在后,ArithmeticException在前),如果发生异常,只会匹配一个catch(分别捕获,相应处理)
例:try{
}catch(ArithmeticException ex){
}catch(Exception ex){
}
5、可以进行try-finally配合使用,这种用法相当于没有捕获异常,因此程序会直接崩掉。只有finally里的程序会最后运行,后面的代码无法运行。
throws异常处理
基本介绍:
(1)如果一个方法(中的语句执行时)可能生成某种异常,但并不能确定如何处理这种异常,则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理。
(2)在方法声明中用throws语句可以声明抛出异常的列表(多个子类异常),throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类(Exception)。
throws细节及注意事项
1、对于编译异常,程序中必须处理
2、对于运行异常,程序中如果没有处理,默认是throws处理
3、子类重写父类方法时,对于抛出异常的规定:子类重写的方法,所抛出的异常类型,要么和父类抛出的异常一致,要么为父类抛出异常的子类型
4、在方法中,如果有了try-catch则不必使用throws