面向对象
面向对象编程(OOP,Object Oriented Programming),本质就是以类的方式组织代码,以对象的组织(封装)数据。
对象的创建分析
使用new关键字创建对象
使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及队形中构造器的调用。
类中构造器也称构造方法,实在进行创建对象的时候必须调用的,并且构造器有以下两个特点:
1.必须和类的名字相同
2.必须没有返回类型,也不能写void
package OPP.demo02; public class student { //属性:字段 String name; int age; //方法 public void study(){ System.out.println(this.name+"在学习"); } }
package OPP.demo02; public class Application { public static void main(String[] args) { //类:抽象的,实例化 //实例化后会返回一个值 //student对象是一个student类的具体实力 student xiaoming = new student(); student xiaohong = new student(); xiaoming.name="秦江"; xiaoming.age=8; System.out.println(xiaohong.name); System.out.println(xiaoming.name); } }
构造器
package OPP.demo02; public class Person { String name; int age; //实例化初始值 //使用new关键字,本质是调用构造器 public Person(){ } //有参构造,一旦定义了有参构造,无参构造就要显示定义 public Person(String name){ this.name=name; } } //Alt+insert 快捷键生成有参,无参
package OPP.demo02; public class Application { public static void main(String[] args) { Person person = new Person("kuangshen"); System.out.println(person.name); } }
面向对象三大特性
封装(高内聚,低耦合),属性私有,get/set
ublic class Demo04 { //属性私有 private String name;//名字 private int id;//学号 private int age; //提供一些外部对象可使用的属性的方法;Public 的get/set方法 public String getName(){ return this.name; } //set方法 public void setName(String name){ this.name=name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { if (age>120||age<0){ this.age=3; }else { this.age = age; } } }
import OPP.Demo04; import OPP.demo03.Pet; /* * 1.提高程序的安全性,保护数据 * 2.隐藏代码的细节 * 3.统一接口 * 4.提高程序的可维护性 * */ public class Application { public static void main(String[] args) { Demo04 s1= new Demo04(); s1.setName("qingjiang"); System.out.println(s1.getName()); s1.setAge(-111);//不合法 System.out.println(s1.getAge());
继承
- 继承是类与类之间的一种关系,除此之外,类与类的关系还有依赖,组合,聚合等。
- 继承关系的两个类,一个是子类(派生类),一个是父类(基类),子类继承父类使用关键字extends来表示。
- 子类和父类之间,从意义上讲应该具有"is a" 的关系。
- Java中类只有单继承,没有多继承。
package OPP.demo02;
import OPP.Demo05.Student;
public class Application {
public static void main(String[] args) {
Student student = new Student();
// student.test("qinjinag");
}
}
package OPP.Demo05; //子类 public class Student extends Person { public Student() { //隐藏代码,调用父类的无参构造 super();//调用父类的构造器必须写在构造器的第一行。 System.out.println("无参构造执行了Student"); } private String name="zhnegjuan"; public Student(String name) { this.name = name; } public void test(String name){ System.out.println(name); System.out.println(this.name); System.out.println(super.name); } }
package OPP.Demo05; //父类 //在Java所有的类,都直接或者间接继承object类 public class Person { public Person() { System.out.println("有参构造执行了Person"); } protected String name="kuangshen"; }
super注意点:
- supper调用父类的构造方法,必须在构造方法的第一个;
- supper必须只能出现在子类的方法或者构造方法中;
- supper和this 不能同时调用构造方法
this
代表的对象不用:
- this :本身调用者这个对象
- supper:代表父类对象的应用
前提
- this :没有继承也可以用
- supper:只能在继承才可以使用
构造方法
- this();本类的构造
- supper();父类的构造
重写:
- 需要有继承关系,子类重写父类的方法!
- 方法名必须相同
- 参数名也必须相同
- 修饰符:范围可以扩大!public>protected>Default>private
- 抛出的异常:范围可以缩小,不能被扩大
- 重写,子类的方法和父类必须一致,方法体不同!
多态(多态是方法的多态,属性没有多态)
- 即同一方法可以根据发送队形的不同而采用多种不同的行为方式
- 一个队形的实际类型是确定的,但可以指向对象的引用的类型有很多
public class Test{ public static void main(String[] args){ show(new Cat());//以Cat对象调用show方法 show(new Dog());//以Dog对象调用show方法 Animal a = new Cat(); //向上转型 a.eat(); //调用的是Cat的eat Cat c = (Cat)a; //向下转型 c.work(); //调用的是Cat的work } public static void show(Animal a){ a.eat(); //类型判断 if(a instanceof Cat){ Cat c = (Cat)a; c.work(); }else if(a instanceof Dog){ Dog d = (Dog)a; d.work(); } } } abstract class Animal{ abstract void eat(); } class Cat extends Animal{ public void eat() { System.out.println("Eat Fish"); } public void work(){ System.out.println("Catch mouse"); } } class Dog extends Animal{ public void eat() { System.out.println("Eat Bone"); } public void work(){ System.out.println("Looking for the House"); } }
多态存在的条件
- 有继承关系
- 子类重写父类的方法
- 父类引用指向子类对象
多态的注意事项:
- 多态是方法的多态,属性没有多态
- 父类和子类有联系,类型转换异常!ClassCastException
- 存在条件:继承关系,方法需要重写。父类引用指向子类的对象。
//父类 public class Father{ public void run{ System.out.println("Father Run"); } } //子类 public class Son extends Father{ @Override public void run{ System.out.println("Son Run"); } public void eat{ System.out.println("Son Eat"); } } //测试类 public class Test{ public static void main(String[] args){ //对象能执行哪些方法,主要看左边的类型,和右边的关系不大 Son son = new Son();//Son 可以执行Son本身和从Father那里继承的方法 Father fa = new Son();//Father可以执行本身的方法,但是不能执行子类特有的方法 son.run();//输出:Son Run fa.run();//输出:Son Run,子类重写父类的方法,则执行子类的方法 son.eat();//输出:Son Eat // fa.eat();//报错,原因:父类不可以调用子类独有的方法 ((Son)fa).eat();//进行类型转换之后,输出:Son Eat } } /** * 1.子类能调用的方法是都是自己的或者继承父类的 * 2.父类能调用的方法是自己的 ,不能调用子类独有的方法 * 3.如果子类对父类的方法进行重写,则执行子类的方法 */
父类引用指向子类的对象 Person person = new Student(); 把子类转换为父类,向上转型 把父类转化为子类,向下转型,强制转型 方便方法的调用,减少重复代码,简洁 抽象:封装、继承、多态
抽象类
abstract 修饰符可用来修饰方法也可修饰类,那该方法就是抽象方法;如果是修饰类,那该类就是抽象类。
抽象类中没有抽象方法,但是有抽象方法的类一定要声明抽象类。
抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。
抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。
public abstract class Action { //抽象方法,只有名字,没有实现 public abstract void doSomething(); //1.不能new这个抽象类,只能靠子类去实现它:约束 //2.抽象类中可以写普通的方法 //3.抽象方法必须在抽象类中 //抽象的抽象:约束 } public class A extends Action{ @Override public void doSomething() { } }
接口
package OPP.Demo08; //类可以实现接口implements //实现接口的类,就需要实现接口中的方法 //多继承interface public class UserServiceImpl implements UserService,TimeService { @Override public void timer() { } @Override public void add(String name) { } @Override public void delete(String name) { } @Override public void update(String name) { } @Override public void query(String name) { } }
内部类及OOP实战
内部类:就是在一个类的内部定义另一个类,比如,A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类对B类来说就是外部类了。
成员内部类、静态内部类、局部内部类、匿名内部类
异常机制介绍
检查性异常
运行时异常
错误Error
try
catch捕获
catch(想要捕获的异常类型) 最高的Throwable
finally
public class Test { public static void main(String[] args) { int a=1; int b =0; try {//try的监控区域 System.out.println(a/b); }catch (ArithmeticException e){//捕获异常 System.out.println("程序出现异常,变量b不能为0"); }finally {//处理善后,终究会被执行 System.out.println("finally"); } } }
package exception; public class Test { public static void main(String[] args) { int a=1; int b =0; //需要捕获多个异常时需从小到大 try {//try的监控区域 new Test().a(); }catch (Error e){ System.out.println("erro"); }catch (Exception e){ System.out.println("exception"); }catch (Throwable t){//捕获异常 System.out.println("程序出现异常"); }finally {//处理善后,终究会被执行 System.out.println("finally"); } } public void a(){ b(); } public void b(){ a(); } }
throw 在方法里主动抛出异常
throws 在方法上抛出异常
异常要从小到大
快捷键CTRL+ALT+T
package exception; public class Test { public static void main(String[] args) { try { new Test().test(1,0); } catch (ArithmeticException e) { e.printStackTrace(); } } //假设这方法中处理不了异常,方法上抛出异常 public void test(int a, int b) throws ArithmeticException{ if (b == 0) { throw new ArithmeticException();//主动抛出异常,一般用在方法中 } } }
package exception; public class Test { static void test(int a) throws MyException { System.out.println("传递的参数为:"+a); if(a>10){ throw new MyException(a);//抛出异常 } System.out.println("ok"); } public static void main(String[]args){ try { test(12); } catch (Exception e) { System.out.println("MyException:"+e); } } }
package exception; //自定义的异常类 public class MyException extends Exception{ //传递数字>10 private int detail; public MyException(int a) { this.detail = a; } //to String;异常的打印消息 @Override public String toString() { return "MyException{" + "detail=" + detail + '}'; } }