Java之面向对象
面向对象
对象其实就是数据和*函数*的封装体
数据表示自身的状态,也称作属性和成员数据
函数表示自身的功能,也称作方法和成员函数
类的编写规范:1,定义成员属性 2,定义构造方法 3,定义成员方法
封装
封装分为两步1,将本组所有相同属性的构造抽象出来和方法进行包装;2, 解决数据的安全性,最主要的方法是权限设置;
继承
继承就是重用现有类来生成新类的一种特征;
就是从现有的类(父类或基类)创建新类(子类或派生类)的过程
再Java中继承可以使代码重用
最高层是最普通的,最一般的情况,往下每一层都比上一层更具体,并包含有高层的特征,通过这样的层次结构使下层的类能自动享用上层类的特点和性质;
继承其实就是自动地共享基类中成员属性和成员方法的机制。
多态
多态是指同一函数在不同的类中有不同的实现
多态的好处就是使类更灵活,更便于扩充
抽象
把相同的或相似的对象归为一类的这个过程就是抽象
抽象的基本原则:1,只关心主要问题,而不关心次要问题;2,只关心主要矛盾,而不关心次要矛盾;3,只关心相同的问题,而不关心不同的问题;4,只关心问题是什么,能完成什么,而不关心怎么去完成
抽象的过程就是面向对象的核心思想
成员属性如果没有赋值,原始型的为0,引用型的为null
代码示例
//student 类定义成员方法与属性
public class Student {
private String name;
private String stuNu;
private int age;
private String sex;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setStuNu(String stuNu) {
this.stuNu = stuNu;
}
public String getStuNu() {
return stuNu;
}
}
接下来是test类对方法的调用,成员属性为私有,不能直接调用,可以用get(),set()来实现方法的调用
public class Test1 { public static void main(String[] args) { Student s= new Student(); s.setAge(10); s.setSex("男"); s.setName("张三"); s.setStuNu("213"); System.out.println(s.getSex()); System.out.println(s.getAge()); System.out.println(s.getName()); System.out.println(s.getStuNu());}
}
构造方法
只要是类一定有构造方法,如果没有在类中定义构造方法,那么编译时由虚拟机自动编译构造方法
自动创建的构造方法为public 无参的构造方法,而且在构造方法中什么都不做
构造方法没有返回值类型,也不能有返回值
一旦我们显示地写出了构造方法,那么虚拟机不在自动产生默认的构造方法
构造函数的名称应该与类名完全相同
public class Student {
private String name;
private String stuNu;
private int age;
private String sex;
\\构造方法写在成员属性与成员方法之间
public Student(){
System.out.println("Student Constructor");
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setStuNu(String stuNu) {
this.stuNu = stuNu;
}
java中,函数被称为方法
定义一个方法的一般形式:[访问权限] 返回值类型 方法名称 (形参列表){ 方法主体 ;}
方法重载
方法重载:方法名相同但参数不同
可以有三方面不同1,数量不同;2,类型不同;3,顺序不同;
编译器会根据调用时传递的实际参数自动判断具体调用的是那个重载方法
要在同一作用域
方法重载与方法的返回值类型没有任何关系
*请勿将功能完全不一样的方法进行重载*
举例:
int abs(int x){....}
float abs(float x){....}
double abs(double x){....}
long abs(long x){....}
this关键字
每个成员都有一个隐含的this引用,它总是指向调用它的对象;
关键字this给出用于调用成员方法的对象的地址
每当调用成员方法时,编译器会向this分配调用该方法的对象的地址;
可以像使用任何引用那样使用this。
在开发时,把形参的名字和成员属性的名字设为一样,可以方便其他人看你的代码
this:当前对象本身
this.:当前对象本身的成员
this():通知虚拟机执行某个构造方法(必须写在构造方法第一句)
static
static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。 如果代码里面出现了过多的静态方法,你的代码就需要“重构”。
如果属性或者方法被static修饰,表示这个属性与方法不再属于对象,而是属于整个类,它会被多个对象共享。被static关键字修饰的不需要创建对象去调用,直接根据类名就可以去访问。也就是说方便在没有创建对象的情况下来进行调用
静态成员方法不能直接访问非静态成员
static方法中绝对不能用this(根本无法调用)
静态成员与程序同生命周期
在没有实列化对象时,可以通过类名来访问对象
也可以通过对象访问静态成员变量,但不论使用那个对象,访问到的都是同一个变量
作业:1,定义一个狗类,要求这个类最多产生一个对象
//单例模式
包
有时候,类与类的名称可能发生冲突;Java提供了把类名空间划分为更容易管理的块的机制,这就是包;
包允许将类组合成较小的单元,类似与文件夹;
有助于避免命名冲突,分属不同包的类,即使名称相同也不会引起误会;
能在包与包之间对于类的访问权限提供更有力的约束。
不能用缺省包(在以后的开发中)禁止使用import xxx.*(导入当前目录下所有类)
强行导包,防止同名异常
对象数组
对象数组的概念: 如果一个数组中的元素是对象类型,则称该数组为对象数组。 当需要一个类的多个对象时,应该用该类的对象数组来表示,通过改变下标值就可以访问到不同的对象。 对象数组的定义和使用: 对象数组的定义与一般数组的定义类似,但是需要为每一个元素实例化。 对象数组的声明形式是: 类名 对象数组名 [ ]; 为对象数组分配内存空间: 对象数组名=new 类名[数组长度];//注意 :此处不是构造方法了
/*作业2:输入n个学生信息并打印
- 要求:1.每个学生有学号(String),姓名(String),年龄(int),性别(char),地址(String)
- 2.学号要求唯一,年龄要求6-60之间,性别要求男或女,任何一个验证失败,该学生信息全部重新输入
- 3.要求使用面向对象封装思想解决该题目,要考虑到每个类功能单一、代码高维护度、低耦合、负载均衡问题 */
//作业讲解1
类的访问权限
还可以在定义类时为类添加访问修饰符,对类进行访问权限控制;
对普通类使用的访问修饰符只有public和缺省两种
被public修饰的类可以从任何地方访问,不受限制;
不加访问修饰符,缺省修饰的类只能从本包中访问,不同包则无法访问到
但要注意的是:在一个源文件中只能有一个被public修饰的类,而且文件名必须于public的类同名;
如果要定义多个public的类,则必须分别写在不同的源文件中,一个源文件只写一个类是良好的编程习概。
访问控制权限列表
继承
继承是单方向的,即派生类可以继承和访问基类中的成员,但基类则无法访问派生类中的成员;
在Java中只允许单一继承方式,即一个派生类只能继承于一个基类,而不能像c++中派生类继承于多个基类的多重继承方式。
构造方法执行顺序,必须先执行父类的构造方法,再执行子类的构造方法
如果父类上还有更高级的父类,就会调用最高父类的构造方法,再逐个依次的将所有继承关系的父类构造方法全部执行
如果父类的构造方法失败,子类的对象实例化也无法实现
jvm规定在使用子类的构造方法创建对象时,默认使用该子类的父类的无参构造方法实例化对象
super关键字
1:在子类的构造方法中,super关键字可以显示地通知虚拟机调用直接父类地构造方法,用于将参数传递给它;其一般语法如下
super(实际参数);
需要注意的是:该语句必须是子类构造方法的第一条语句。
2:super.显示的调用父类成员
super.不能越级使用(不能出现super.super.)
方法覆盖
在继承关系中,如果在父类和子类中都定义了相同的方法(方法名,参数列表都一样),则子类的方法将覆盖父类的方法。这称为方法重写(方法覆盖),英文叫做“ override ”,此时为了显示的表明是重写的方法可以加一个注解“@Override”,上面的实例就可以加上一个注解。
区分方法覆盖和方法重载
方法覆盖出现的前提条件之一是必须有继承方式的情况下,而且要求父类和子类中的方法必须同原型
方法重载时,继承并不是必需的,它只要求方法名称相同,而参数列表则必须不同,换言之,各方法的原型其实是不同的
引用转型
多态
静态多态
静态多态也称为编译时多态,即在编译时决定调用哪个方法
静态多态一般是指方法重载
只要构成了方法重载,就可以认为形成了静态多态的条件
静态多态与是否发生继承没有必然联系
动态多态
动态多态也称为运行时多态,即在运行时决定调用哪个方法
形成动态多态必须具备的条件:
1,必须要有继承的情况存在;
2,在继承中必须要有方法覆盖;
3,必须由基类的引用指向派生类的实例,并且通过基类的引用调用被覆盖的方法;
继承是实现动态多态的首要前提
抽象方法
在某些情况下,基类无法提供被覆盖方法的具体实现。那么就可以将此方法声明成抽象方法;
使用关键字abstract声明抽象方法,一般语法:
[访问权限] abstract 返回值类型 方法名称(参数列表);
如:public abstract void draw();
abstract和static不能一起用
如果一个类中有抽象方法,那么这个类必须是抽象类
1,抽象类中可以有抽象方法,也可以有非抽象方法
2,抽象类的子类必须实现所有抽象类的方法,除非该子类也是抽象类
3,抽象类不能直接实例化(不能直接new 构造)
接口
如果某个类中所有方法都是抽象方法,那么可以考虑将该类定义为接口;
定义接口使用关键字interface,一般语法: [访问权限] interface 接口名 { 成员列表}
如:public interface Myinterface { }
1,接口中所有的方法皆为抽象
2,接口中所有的成员为public
3,接口可以被类多实现,也可以被接口继承
4,接口不是类,所以没有构造方法
5,接口不能实例化
6,接口的成员属性皆public static final
7,jdk>=1.8允许有static和default方法(慎用)
思考:接口与抽象类的区别
final关键字
在Java中,final关键字有最终的,不可修改的含义;
final关键字有三种用途,可以分别应用于变量,成员方法和类
如果将某个成员方法修饰为final,则意味着该方法不能被子类覆盖,一般语法:
[访问权限] final 返回值类型 方法名(参数列表){ }
如:public final void fun(){ }
如果在派生类中出现同原型的方法我,将会报错。
如果将某个类修饰为final,则意味着该类无法被继承,一般语法:
[访问权限] final class 类名 { 成员列表}
如:public final class Myclass{ }
任何类想继承Myclass类都将报错
作业:手机的功能
内部类
提高更加严的访问性
先是成员后是类
1,内部类要访问保护它的类的成员可以直接访问,但不能使用this
2,内部类的访问权限可以有4个
3,内部类经过编译后生成的字节码,包含它的类名$自己的类名
4,内部类的成员包含它的类要访问的话,要通过对象访问
5,在其他类中要访问内部类。new 外部类().new(内部类)
异常
异常可分为两大类:编译时异常和运行时异常;
编译时异常
编译时异常一般是指语法错误,可以通过编译器的提示加以修正
运行时异常
运行时异常包括:
运行错误:除数为零、空引用、数组下标越界等
逻辑错误:如年龄超过200岁等
try块:一般用来监视有可能产生异常的代码部分;
catch块:当异常产生后,catch块捕捉异常,并在其中对异常进行处理
一般形式:
异常发生时,写在try中异常的后续代码不再执行
finally块
无论try/catch块中发生了什么,finally都一定会执行
当异常发生时,程序可能会意外中断,有些被占用的资源就得不到清理。fianlly块可以确保执行所有的清理工作
finally是可选的,可视具体情况决定是否添加;
finally块必须和try块一起使用,不能单独存在
异常类体系结构图
多重catch块
举例:
public class Test {
public static void main(String[] args) {
try{
int num1 = Integer.parseInt(args[]);
int num2 = Integer.parseInt(args[1]);
int result = num1/num2;
System.out.println(result);
}catch(ArithmeticException e){
System.out.println("算数异常"+e.getMessage());
e.printStackTrace();
}catch(NumberFormatException e){
System.out.println("数字格式异常"+e.getMessage());
e.printStackTrace();
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("数组下标越界异常"+e.getMessage());
e.printStackTrace();
}catch(Exception e){
System.out.out.println("其他异常"+e.getMessage());
e.printStackTrace();
}
}
}
throw和throws
throw:手工抛出异常
throw(异常实例)
throws:向上(方法的调用者)抛异常
在方法覆盖时,子类的方法不能比父类的访问权限更严的访问权限
在方法覆盖时,子类throws的异常不能比父类的方法的throws异常更大

浙公网安备 33010602011771号