目录
一 面向对象三大特性
三大特性:封装、继承、多态
1 封装
定义:在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。
程序追求 高内聚、低耦合;
封装(数据的隐藏)通常,应禁止直接访问一个对象中数据的实际表示,而通过操作接口来访问,这称为信息隐藏。
属性私有,get/set方法进行调用或赋值
简单例题:
package OOP.Encapsulation_fengzhuang;
//类 private:私有
public class Student {
//属性私有
private String name;//名字
private int id;//学号
private char sex;//性别
//get和set方法,实现外部可以调用或赋值
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
//使用alt+insert 可以快速生成get/set方法
}
package OOP.Encapsulation_fengzhuang;
public class Demo01 {
public static void main(String[] args) {
//实例化一个Student类
Student s1 = new Student();
// s1.name(); //这种方法的错误的,因为name是私有的
//通过get/set方法对私有属性进行调用或赋值
s1.getName();
System.out.println("实例化的对象S1的name值:" +s1.getName());
s1.setName("yuan");
System.out.println("set后对象S1的name值:" +s1.getName());
}
}
通过封装,可以在外界调用set时,对输入参数进行合法性判断。
/通过封装,可以在调用set方法时对输入值进行合法性判断
public void setAge(int age) {
if(age >100 || age<0){
System.out.println("年龄输入不合法");
}else{
this.age = age;
}
}
s1.setAge(123);//会被set的合法性判断拦截,输出值仍为默认值
System.out.println(s1.getAge());
封装的好处:1 提高程序的安全性,保护数据
2 隐藏代码的实现细节
3 统一接口
4 系统可维护增加
2 继承
(1)定义:关键字 extands;继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为
java中只有单继承,没有多继承。
继承是类与类之间的一种关系。除此之外,还有依赖、组合、聚合等关系;
继承关系的两个类,一个为父类(基类),一个为子类(派生类),子类继承父类。
子类和父类之间,从意义上讲应该具有”is a“的关系。即dog是一种动物;
快捷键:ctrl+H 查看子类父类继承树
例题:Person为父类,有一个say方法;Student为子类,继承Person
package OOP.extands_jicheng;
//父类
//在java中,所有的类,都默认直接或间接继承object类
public class Person {
String name;
public void say(){
System.out.println("会说话");
}
}
package OOP.extands_jicheng;
//学生,学生 is a person;继承person类
public class Student extends Person{
//子类继承了父类,会拥有父类的全部方法;
//创建一个student对象时,虽然在此处什么也没定义,但父类的公有方法 public都可以用
//但私有的private 不能被继承
}
main类:
package OOP.extands_jicheng;
public class Demo01 {
public static void main(String[] args) {
//因为Student继承了person类,所以虽然student中没有定义say方法,但也可以用
Student S2 = new Student();
S2.say();
}
}
(2) object类
在java中,所有的类,都默认直接或间接继承object类
(3)super
super注意点:
1 super调用父类的构造方法,必须在构造方法的第一个
2 super必须只能出现在子类的方法或者构造方法中
3 super和this不能同时调用构造方法
和this的区别
代表的对象不同:this 本身调用者这个对象;super 代表父类对象的应用
前提不同:this 没有继承也可以使用;super 只能在继承条件下才能使用
构造方法:this() 本类的构造; super() 父类的构造
例题:
父类:
package OOP.extands_jicheng;
//父类
//在java中,所有的类,都默认直接或间接继承object类
public class Person {
// String name;
public void say() {
System.out.println("会说话");
}
//super的例子
//1 属性值的测试
protected String name = "kuangshen";
//2 方法的测试
public void print() {
System.out.println("person");
}
//3 构造器
public Person() {
System.out.println("Person无参执行了");
}
public Person(String name) {
this.name = name;
}
}
子类:
package OOP.extands_jicheng;
import com.sun.org.apache.xerces.internal.impl.xpath.XPath;
//学生,学生 is a person;继承person类
public class Student extends Person {
//子类继承了父类,会拥有父类的全部方法;
//创建一个student对象时,虽然在此处什么也没定义,但父类的公有方法 public都可以用
//但私有的private 不能被继承
//super例子
//1 属性值的测试
private String name = "qinjiang";
public void test(String name) {
System.out.println(name);//输出传入参数
System.out.println(this.name);//输出子类定义的私有属性值
System.out.println(super.name);//输出父类的属性值
}
//2 方法的测试
public void print() {
System.out.println("student");
}
public void test2() {
print(); //先输出student类的print方法
this.print();//输出student类的print方法
super.print();//输出person类的print方法
}
//3 构造器
//输出结果显示,子类默认首先调用了父类的无参构造,之后执行自己的
public Student() {
//此处隐藏了父类的无参构造
//可以显示,但必须是第一行
super();//调用无参构造
// super("name");//可以不写
System.out.println("Student无参执行了");
}
//如果父类使用了有参构造,必须显式写出无参构造,否则子类调用父类无参构造会报错;但直接调用有参构造可以使用
}
main类:
package OOP.extands_jicheng;
import com.sun.org.apache.xerces.internal.impl.xpath.XPath;
//学生,学生 is a person;继承person类
public class Student extends Person {
//子类继承了父类,会拥有父类的全部方法;
//创建一个student对象时,虽然在此处什么也没定义,但父类的公有方法 public都可以用
//但私有的private 不能被继承
//super例子
//1 属性值的测试
private String name = "qinjiang";
public void test(String name) {
System.out.println(name);//输出传入参数
System.out.println(this.name);//输出子类定义的私有属性值
System.out.println(super.name);//输出父类的属性值
}
//2 方法的测试
public void print() {
System.out.println("student");
}
public void test2() {
print(); //先输出student类的print方法
this.print();//输出student类的print方法
super.print();//输出person类的print方法
}
//3 构造器
//输出结果显示,子类默认首先调用了父类的无参构造,之后执行自己的
public Student() {
//此处隐藏了父类的无参构造
//可以显示,但必须是第一行
super();//调用无参构造
// super("name");//可以不写
System.out.println("Student无参执行了");
}
//如果父类使用了有参构造,必须显式写出无参构造,否则子类调用父类无参构造会报错;但直接调用有参构造可以使用
}
(4)方法重写
前提:需要有继承关系,子类重写父类的方法
1 方法名必须相同;
2 参数列表必须相同;
3 修饰符:范围可以扩大但不能缩小 :public > Protected>Default>private
4 抛出的异常:范围,可以被缩小,但不能扩大; ClassNotFoundException--->Exception(大)
重写,子类的方法和父类必须一致;方法体不同
为什么重写:1 父类的功能,子类不一定需要或者不一定满足;
快捷键:alt + Insert : override
例题:
父类:
package OOP.extands_jicheng;
//B是父类
public class B {
// //父类定义的方法test
public static void test() {
System.out.println("B=>test()");
}
//父类定义的方法test2
public void test2() {
System.out.println("B=>test2");
}
}
子类:
package OOP.extands_jicheng;
//A继承于B,A是子类
public class A extends B {
// //A 自定义test方法
public static void test() {
System.out.println("A=>test()");
}
//重写父类的方法 Override
@Override //注解:有功能的注释
public void test2() {
System.out.println("A=>test2()");
}
}
主类:
package OOP.extands_jicheng;
public class Demo02 {
public static void main(String[] args) {
//方法的调用只和左边有关
A a = new A();
a.test(); //输出为A定义的方法
//父类的引用指向子类是允许的
B b = new A();
b.test(); //输出是B定义的方法
//重写方法测试,非静态方法,子类重写了父类的方法
//输出都是子类的方法输出
a.test2();
b.test2();
}
3 多态
定义:多态是同一个行为具有多个不同表现形式或形态的能力。多态就是同一个接口,使用不同的实例而执行不同操作。
课程中的定义:即同一方法可以根据发送对象的不通过而采用不同的行为方式。
一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多。
多态存在的条件:1 有继承关系
2 子类重写父类的方法
3 父类引用指向子类对象
注意:多态是方法的多态,属性没有多态;
另外:static 方法,属于类,它不属于实例; private 方法, finnal 常量这三种是没有多态的。
例题:
父类:
package OOP.polymorphism_duotai;
//父类
public class Person {
public void run(){
System.out.println("父类的run");
}
public void study(){
System.out.println("person");
}
}
子类:
package OOP.polymorphism_duotai;
//子类
public class Student extends Person{
public void eat(){
System.out.println("子类的son");
}
@Override
public void study() {
System.out.println("子类重写的方法");
}
}
主类:
package OOP.polymorphism_duotai;
public class Demo01 {
public static void main(String[] args) {
//一个对象的实际类型是确定的
// new Student();
// new Person();
//可以指向的引用类型就不确定了
Student s1 = new Student();
Person s2 = new Student();
Object s3 = new Student();
s2.run();//可以调用父类的方法
s1.run();//可以调用父类的方法
System.out.println("---------------");
s1.eat();//只能子类可以调用自己独有的方法
//s2.eat(); //父类调用会报错
((Student) s2).eat();//强制转换成子类类型后可以调用
System.out.println("---------------");
s1.study();//子类重写方法后,输出是子类重写后的方法
s2.study();//子类重写方法后,输出是子类重写后的方法
}
}
instanceof (类型转换) 引用类型,判断一个对象是什么类型;
范围大小顺序:Object >person=String > student = teacher
例题:A :person B: student C teacher
package OOP.polymorphism_duotai;
public class Demo02 {
public static void main(String[] args) {
//范围大小顺序 Object > A = String > B = C
Object a = new B();
//System.out.println(X instanceof Y); //能不能编译通过
//如果左边是右边的子类,则为true
System.out.println(a instanceof Object);//true
System.out.println(a instanceof A);//true
System.out.println(a instanceof B);//true
System.out.println(a instanceof C);//false,和B同属于A的子类
System.out.println(a instanceof String);//false
System.out.println("--------------");
A b = new B();
System.out.println(b instanceof Object);//true
System.out.println(b instanceof A);//true
System.out.println(b instanceof B);//true
System.out.println(b instanceof C);//false
//System.out.println(b instanceof String); //flase 会编译报错
System.out.println("---------------");
B c = new B();
System.out.println(c instanceof Object);//true
System.out.println(c instanceof A);//true
System.out.println(c instanceof B);//true
//System.out.println(c instanceof C);//true //FALSE 会编译错误
}
}
类型转换:
子类转换为父类,向上转型,可能会丢失掉自己独有的子类方法
父类转换为子类,向下转型,需要强制转换,丢失精度,但会获得子类的独有的方法
public class Demo02 {
public static void main(String[] args) {
A obj = new B(); //A 是父类,B是子类
//可以将这个对象转换为子类的类型,然后使用子类的方法
((B) obj).go(); //把父类转换为子类,强制转换
B obj2 = new B();
//子类转换为父类,向上转型
//作用是方便方法的调用,减少重复的代码
Static 关键字详解
修饰属性时称为静态属性;修饰方法时称为静态方法。修饰代码块时称为静态代码块。
package OOP.polymorphism_duotai;
//static详解
public class static_1 {
private static int age; //静态变量
private double score; //非静态变量
//非静态方法
public void run() {
System.out.println("run");
}
//静态方法
public static void go() {
System.out.println("go");
}
//匿名静态代码块,创建类的时候就会被执行,会第二个被执行,可以用来赋初始值
{ //代码块
System.out.println("匿名代码块");
} //匿名代码块
//静态代码块,创建类的时候就会被执行,会首先被执行,且只被执行一次
static {
//代码块
System.out.println("静态代码块");
}
public static void main(String[] args) {
static_1 student = new static_1();
//静态属性,与非静态属性
System.out.println(static_1.age);//静态变量可以直接引用
//System.out.println(static_1.score); //非静态变量不可以直接引用
System.out.println(student.age);//静态变量可以直接引用
System.out.println(student.score);//非静态变量可以直接引用
//静态方法,非静态方法
// run(); //非静态方法直接调用不可以
go();//静态方法直接调用就可以
student.run();//实例化后可以直接调用
student.go();//实例化后也可以直接调用
//静态代码块,创建类的时候就会被执行
}
}
二 抽象类和接口
(1)抽象类:
abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。
1 抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。
2 抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。
3 抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
4 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。
5 抽象类存在的意义:提升开发效率
抽象类:
package OOP.Abstract;
//抽象类 abstract
public abstract class Action {
//抽象方法:1 只有名字,没有实现;2 抽象类必须在抽象方法中
//3 不能new, 只能靠子类来实现
public abstract void fun();
//普通方法,抽象类中可以写普通方法
public void doSomething(){
}
}
继承抽象类的子类:
package OOP.Abstract;
public class A extends Action{
@Override
public void fun() {
System.out.println("重写的抽象方法");
}
}
(2)接口
接口:只有约束,没有实现;也就是说只有抽象方法。
定义:接口就是规范,定义的是一组规则。接口的本质是契约。OO的精髓,是对对象的抽象,而最能体现这一点的就是接口。
关键字:声明接口的关键字是interface。
三者的区别:普通类---只有具体实现; 抽象类---具体实现和规范(抽象方法)都有;接口---只有规范(抽象方法)。
例子:
接口:
package OOP.Interface;
//interface 定义接口的关键字
public interface UserService {
//接口中所有的定义都是抽象的 相当于隐藏了public abstract
public abstract void add(String name);//默认是前面有public abstract
void del(String name);
void update(String name);
void query(String name);
//在接口中定义属性时,其实时定义常量
public static final int AGE = 99;
}
实现接口的类:(可以多继承,继承多个接口)
package OOP.Interface;
//继承接口,重写接口的方法
public class UserServiceImpl implements UserService{
@Override
public void add(String name) {
}
@Override
public void del(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
}
接口的作用:
1 约束
2 定义一些方法,让不同的人实现
3 方法都是public abstract 可以直接调用
4 接口中的属性都是 public static fina 常数,可以直接使用
5 接口不能被实例化,接口中没有构造方法
6 implements可以实现多个接口
7 必须要重写接口中的方法。
三 内部类
内部类就是在一个类的内部再定义一个类,例如,A类中定义一个B类,那么B类相对于A类来说就是内部类,而A就是B的外部类。
1 成员内部类
2 静态内部类
3 局部内部类
4 匿名内部类
package OOP.inclass;
public class Outer {
private int id = 10;
public void out() {
System.out.println("这是外部类的方法");
}
// 在外部类的方法中写入类,叫局部内部类
public void out_2() {
class Inner_3 {
public void in_3() {
System.out.println("局部内部类");
}
}
}
//成员内部类
public class Inner {
public void in() {
System.out.println("这是内部类的方法");
}
//用途之一,可以获得外部类的私有属性
public void getID() {
System.out.println(id);
}
}
//静态内部类:带static的内部类
public static class Inner_2 {
public void in() {
System.out.println("这是静态内部类");
}
}
//匿名类,直接new,但没有起名字
// new A().in_4; 在main方法中可以用。
}
//一个class只能有一个public类,可以有多个非public的类
class A {
public void in_4() {
System.out.println("这也是一个内部类");
}
}