面向对象的三大特性
封装
-
封装:
私有的属性要用get、set方法来使用(快捷键:alt+insert)
还可以对于一些不合法的情况进行处理 。public class Student { //属性私有 private String name;//名字 private int id;//学号 private char sex;//性别 private int age;//年龄 //生成get、set方法 public int getAge() { return age; } public void setAge(int age) { //不合法处理 if (age>120||age<0){ this.age = 3; }else { this.age = age; } } }
public class Demo05 { public static void main(String[] args) { Student student = new Student(); student.setAge(999);//不合法 System.out.println(student.getAge()); } }
//输出 3
- 封装的好处:
- 提高程序的安全性,保护数据。
- 隐藏代码的实现细节。
- 统一接口
- 系统可维护性增加了
- 回顾下方法的重载:判断两个方法是否是同一个
- 方法名相同
- 传参相同
- 封装的好处:
继承
-
继承
-
子类可以继承父类的所有方法
-
public修饰的属性可以继承 ,private修饰的属性不能继承
-
四种修饰符:
- public
- protected
- default
- private
-
查看继承树关系:
- 选中该类后按快捷键ctrl+H
- 选中该类后按快捷键ctrl+H
-
在Java中所有的类都默认直接或间接继承object类
-
-
super:调用父类的构造方法
//启动类 public class Application { public static void main(String[] args) { Student student = new Student(); student.test("wyf"); } }
//student派生类 public class Student extends Person { private String name = "whl"; public void test(String name){ System.out.println(name);//wyf System.out.println(this.name);//whl System.out.println(super.name);//human } }
//person父类 public class Person /* extends Object */{ protected String name = "human"; }
-
私有的东西无法被继承!
-
new一个student的时候,默认先调用了person的无参构造。
-
super的东西,必须放在代码的第一行;即,调用父类的构造器,必须放在子类构造器的第一行。
-
super默认调用的是无参构造。
super注意点:
- super调用父类的构造方法,必须在构造方法的第一个
- super必须只能出现在子类的方法或者构造方法中
- super和this不能同时调用构造方法
super vs this:
- 代表的对象不同:
- this:本身调用者这个对象
- super:父类对象的引用
- 前提:
- this:没有继承也可以使用
- super:只能在继承条件下使用
- 构造方法:
- this():本类的构造
- super():父类的构造
//启动类 public class Application { public static void main(String[] args) { Student student = new Student(); } }
//student类 public class Student extends Person { private String name = "whl"; public Student(){ //super();//隐式的,可以不写 System.out.println("student无参被执行了"); } }
//person类 public class Person /* extends Object */{ protected String name = "human"; public Person(){ System.out.println("person无参被执行了"); } }
//输出 person无参被执行了 student无参被执行了
-
-
方法重写
-
都是方法的重写,与属性无关。
例1:static静态方法
方法的调用只和左边的类型有关系
//启动类 public class Application { public static void main(String[] args) { //方法的调用,只和左边的类型有关 A a = new A(); a.test();//A的静态方法 //父类的引用指向了子类 B b = new A(); b.test();//B的静态方法 } }
public class B { public static void test(){ System.out.println("B"); } }
public class A extends B { public static void test(){ System.out.println("A"); } }
//输出 A B
-
静态的方法和非静态的方法,不一样。
例2:非静态方法
子类重写了父类的方法,方法只和非静态有关
public class Application { public static void main(String[] args) { A a = new A(); a.test(); B b = new A(); b.test(); } }
public class B { public void test(){ System.out.println("B"); } }
public class A extends B { public void test(){ System.out.println("A"); } }
//输出 A A
-
子类继承了父类,才能重写。
重写快捷键:alt+insert
public class A extends B { // public void test(){ // System.out.println("A"); // } @Override public void test() { super.test(); } }
-
注意点:
-
重写:
-
需要有继承关系,子类重写父类的方法。
-
方法名必须相同。
-
参数列表必须相同。
-
修饰符,范围可以扩大但不能缩小;public > protected > default > private
-
抛出的异常,范围可以被缩小,但不能扩大。
-
子类的方法名和父类一致,但方法体不同。
-
快捷键:alt + insert override
-
-
为什么需要重写:
- 父类的功能,子类不一定需要,或者不一定满足。
-
-
多态
-
多态
即,同一方法可以根据发送对象的不同而采用多种不同的行为方式。使得程序更灵活。
-
实现动态编译;
-
一个对象的实际类型是确定的,但可以指向的引用类型不确定了
-
子类重写了父类的方法,就执行子类的方法。没有重写父类,就调用子类的。
//启动类 public class Application { public static void main(String[] args) { Student s1 = new Student(); Person s2 = new Student();//父类的引用指向子类;都是学生,但是表现出多种状态 Object s3 = new Student(); s1.run(); s2.run(); } }
//派生类 public class Student extends Person { @Override public void run() { System.out.println("son run"); } }
//父类 public class Person /* extends Object */{ public void run(){ System.out.println("person run"); } }
//输出 son run son run
-
对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
//启动类 public class Application { public static void main(String[] args) { Student s1 = new Student(); Person s2 = new Student();//父类的引用指向子类;都是学生,但是表现出多种状态 Object s3 = new Student(); s1.run(); s2.run(); s1.eat(); ((Student) s2).eat();//这里将s2强制转化成student类型 } }
//派生类 public class Student extends Person { @Override public void run() { System.out.println("son run"); } public void eat(){ System.out.println("son eat"); } }
//父类 public class Person /* extends Object */{ public void run(){ System.out.println("person run"); } }
-
注意:
-
多态是方法的多态,属性没有多态。
-
父类和子类之间的转换是有联系的,不能瞎转换,会出现类转换异常(ClassCastException)。
-
子类能调用的方法都是自己的,或者继承父类的
-
父类,可以指向子类,但是不能调用子类独有的方法
-
多态存在的条件:
- 继承关系
- 方法需要重写
- 父类引用指向子类对象;即,
Father f = new Son();
-
有些方法不能重写
- static方法:属于类,不属于任何实例
- final修饰的:在常量池中,被final修饰的类没有子类
- private修饰的:私有的,不能重写
-
-
-
instanceof
关键词,判断一个对象是什么类型。
System.out.println(X instanceof Y);
编译能否通过,取决于是否存在父子关系。public class Application { public static void main(String[] args) { Object o = new Student(); //Object > Person > Student //Object > Person > Teacher //Object > String System.out.println(o instanceof Student); System.out.println(o instanceof Person); System.out.println(o instanceof Object); System.out.println(o instanceof Teacher); System.out.println(o instanceof String); } }
true true true false false
-
类型转换
- 把子类转换为父类,向上转型;
- 把父类转换为子类,向下转型;强制转换
-
static关键字
-
匿名代码块,程序在执行时并不能主动调用匿名代码块,创建对象时自动创建,在构造器之前。
-
static静态代码块,类加载时直接执行,只执行一次。
public class Person { { System.out.println("匿名代码块"); } static { System.out.println("静态代码块"); } public Person() { System.out.println("构造器"); } public static void main(String[] args) { Person person = new Person(); System.out.println("========================"); Person person2 = new Person(); } }
//输出 静态代码块 匿名代码块 构造器 ======================== 匿名代码块 构造器
-
静态导入包
比如
Math.random()
方法,不想写太长,可以这么写:package com.oop.demo11; import static java.lang.Math.random; public class Test { public static void main(String[] args) { System.out.println(random()); } }
-
-
抽象类
-
class前加了
abstract
就是抽象类 -
抽象方法,只有方法名,没有具体的方法实现。
-
抽象类的所有方法,继承了它的子类,都必须要实现它的方法。
-
抽象类不能new,只能靠子类去实现它。
-
抽象类中可以写普通方法。
-
抽象方法必须在抽象类中。
-
思考:
- 抽象类存在构造器吗?存在
- 抽象类存在的意义?将共有属性抽象出来,再去处理具体方法;提高开发效率,可扩展性更高。
//抽象类 public abstract class Demo12 { public abstract void doSomething(); public Demo12() { } }
//子类继承并实现 public class Action extends Demo12 { @Override public void doSomething() { } }
-
接口
-
接口
-
关键字
interface
。 -
Java的类是单继承,但是Java的接口可以多继承。
-
比较接口、普通类、抽象类
- 普通类:只有具体实现。
- 抽象类:具体实现和规范(抽象方法)都有。
- 接口:只有规范,自己无法写方法。约束和实现分离。
三者图标:
-
接口的本质是契约。
-
面向对象的精髓是接口。
-
接口中的所有定义都是抽象的。
-
接口都需要有实现类。类通过
implements
实现接口。而实现了接口的类,必须要重写接口中的方法。//接口1 public interface UserService { void add(String name); void delete(String name); void update(String name); void search(String name); }
//接口2 public interface TimService { void timer(); }
//接口实现类 public class UserServiceImpl implements UserService, TimService{ @Override public void add(String name) { } @Override public void delete(String name) { } @Override public void update(String name) { } @Override public void search(String name) { } @Override public void timer() { } }
总结:
-
接口是一种约束。
-
定义一些方法,让不同的人去实现。
-
接口中的方法都是
public abstract
。 -
接口中的常量都是
public static final
。 -
接口不能被实例化,因为没有构造方法。
-
接口可以实现多个,通过
implements
关键字实现,实现类必须要重写接口中的所有方法。
-
-
内部类
-
内部类
就是在一个类的内部再定义一个类,比如:A类中定义一个B类,那么B类相对于A类来说就称为内部类,而A类相对于B类来说就是外部类。
- 分类:
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类
- 内部类可以访问外部的私有属性。
例1:成员内部类
public class Outer { private int number = 10; public void outer(){ System.out.println("外部类的方法"); } class Inner{ public void getNumber(){ System.out.println("number = "+number); } } }
public class Application { public static void main(String[] args) { Outer outer = new Outer(); Outer.Inner inner = outer.new Inner(); inner.getNumber(); } }
注意:内部类中访问私有属性的方法如果加
static
关键字,那么私有属性处也需要加static
。例2:静态内部类(无法直接访问非静态的属性)
public class Outer { private static int number = 10; public void outer(){ System.out.println("外部类的方法"); } static class Inner{ public static void getNumber(){ System.out.println("number = "+number); } } }
- 一个java文件中只能有一个
public class
,但是可以有多个class
例3:匿名内部类
public class OuterTwo { public static void main(String[] args) { } } class A{//匿名内部类 public static void main(String[] args) { } }
public class OuterTwo { public static void main(String[] args) { new A().eat();//匿名对象,不用将实例保存到变量中 } } class A{ public void eat(){ System.out.println("eat"); } }
甚至还可以new一个内部接口
public class OuterTwo { public static void main(String[] args) { CustomerService customerService = new CustomerService() { @Override public void hello() { } }; } } interface CustomerService{ void hello(); }
例4:局部内部类
public class OuterThree { public void run(){ class Inner{//局部内部类 public void in(){ } } } }
另外,内部类不推荐写,但是要了解。
- 分类: