回顾java基础语法之面向对象

这篇文章将复习java中面向对象的特性

基本概念

面向对象 以类的方式组织代码 以对象形式的组织封装数据
面向对象三大特征 封装 继承 多态
先有对象后有类 对象是具体的事物 是对抽象概念的具体实例 类是抽象的 是对对象的抽象

对象

创建一个对象 有static关键字的是从属于类而非对象的静态方法
无static关键字的方法是需要类实例化之后才存在

public class Student {
    //和类一起加载的
    public static void sayHello(){
        System.out.println("Hello");
    }
    //类实例化之后才存在
    public void sayHi(){
        System.out.println("hi");
    }
}

分别调用这两个方法

 		//调用静态方法 类名.方法名
        Student.sayHello();
        //调用成员方法
        Student student = new Student();
        student.sayHi();

java中的值传递和引用传递 请看下面的两个方法

	public static void change(Person p){
        p.name = "abc";
    }
    public static void change(String s){
        s = "abc";
    }

调用这两个方法 第一种就是值传递 不会改变s的内容
第二种引用传递 传递的是对象的引用(指针)会改变内容

		String s = "aaa";
        change(s);
        System.out.println(s); //aaa

        Person p1 = new Person();
        change(p1);  //引用传递
        System.out.println(p1.name); //abc

构造方法

构造器(构造方法) 创建对象的时候会调用
如果不写也会存在构造方法(默认无参构造器)
写了有参构造器 无参构造器就没了 不过通常要写无参构造器
构造方法名字必须和类名相同 且没有返回值
其作用是实例化一些对象
idea中alt+insert可以自动生成构造器
this关键字就是代指这个类 谁调用这个类 this就是谁
程序要追求高内聚 低耦合

public class Student {
    String name;
    int age;
    
    public Student(){
    }
    
    public Student(String name , int age){
        this.name = name;
        this.age = age;
    }
    
    public void study(){
        System.out.println(this.name + " is study");
    }
}

在main方法中测试

        Student student = new Student();
        student.name = "Jack";
        student.study();

        Student student2 = new Student("Bob", 24);
        System.out.println(student2.name + " " + student2.age);

封装

通俗点说 就是把数据封装起来 对外提供一个接口
提高程序的安全性 隐藏代码细节 统一了接口 提高了系统的可维护性
简单来说 属性私有 提供set get
请看下面的代码 private关键字 使得属性和方法只能在本类中调用 别的类中访问不到

class Student{
    //属性私有 get set
    private String name;
    private int age;

    //提供public get set 方法
    public String getName(){
        return this.name;
    }

    public void setName(String name){
        this.name = name;
    }
}

调用setter和getter方法

	 public static void main(String[] args) {
        Student student = new Student();
        student.setName("Jerry");
        System.out.println(student.getName());
    }

继承

继承的本质是对类的抽象 实现对现实世界更好的建模
子类继承父类 就会拥有父类的全部不私有的方法和属性
而使用private关键字的属性和方法不会被继承
通过final修饰的类不能被继承
适用范围 public protected default private
在java中所有的类都继承object类
java中只能单继承 一个子类只能有一个父类

请看下面的代码 子类中没有say()方法 但是继承(extends关键字)后可以调用父类的方法

public class Test01 {
    public static void main(String[] args) {
        Student student = new Student();
        student.say(); //hello
    }
}

class Person{
    public void say(){
        System.out.println("hello");
    }
}

class Student extends Person{
    //子类是父类的拓展
}

用super关键字可以访问父类的属性和方法

public class Test01 {
    public static void main(String[] args) {
        Student student = new Student();
        student.test(); // Teemo Teemo jack
        student.test2(); //test hello
    }
}


class Person{
    protected String name = "jack";

    public void say(){
        System.out.println("hello");
    }
}

class Student extends Person{
    //子类是父类的拓展
    private String name = "Teemo";

    public void test(){
        System.out.println(name);
        System.out.println(this.name);
        System.out.println(super.name);
    }
    
    public void say(){
        System.out.println("test");
    }

    public void test2(){
        say();
        super.say();
    }
}

子类继承父类之后 创建对象的时候会默认调用父类的无参构造器
原因是子类无参构造第一样隐藏了一个super();这个方法会调用父类的无参构造
这句话只能放在第一行 也可以super(xxx);里面放上参数(父类的有参构造器)
当然可以用this();代替(调用子类的无参构造)当然也只能放在构造器的第一行

	public Student(){
        super("jack");
    }

关于方法重写 当在子类写出一个方法方法名 返回值 形参类型一致时 (修饰符范围可以扩大 抛出的异常可以被缩小但不能被扩大) (对final修饰的不能重写)子类调用这个方法 会优先调用子类的这个写出来的方法 请看下面的代码

public class Test01 {
    public static void main(String[] args) {
        B b = new B();//方法重写
        b.test1(); //B test1
    }
}

class A{
    public void test1(){
        System.out.println("A  test1");
    }
}

class B extends A{
    public void test1(){
        System.out.println("B test1");
    }
}

多态

多态可以使我们能够动态编译 可拓展性更强 能让程序变的更灵活
多态是方法的多态 属性没有多态
父类和子类必须有关系
个人理解 s2调用方法的时候 现在父类里面找到那个方法 找不到就不能调用(比如test2()方法)找到之后检查子类是否重写了 如果重写了就调用重写之后的方法
s1则是直接在子类中找这个方法 找不到再去父类中找 也是调用的重写之后的

public class Test01 {
    public static void main(String[] args) {

        Student s1 = new Student();
        //父类的引用指向子类
        Person s2 = new Student();
        Object s3 = new Student();

        //子类重写了父类的方法 就调用子类的
        s2.test1(); //Student test2
        //没有重写就调用父类的方法
        s2.test3(); //Person test3
    }
}

class Person{
    public void test1(){
        System.out.println("Person test1");
    }
    public void test3(){
        System.out.println("Person test3");
    }
}

class Student extends Person{
    public void test1(){
        System.out.println("Student test2");
    }
    public void test2(){
        System.out.println("Student test2 ");
    }
}

请看下面的代码 父类型引用指向子类型对象 上来寻找的是左边的那个类

public class Test01 {
    public static void main(String[] args) {
        A a = new B();
        B b = new B();//方法重写
        a.test1(); //B test1
        b.test1(); //B test1

        //static方法从属于类
        a.test2(); //static A
        b.test2(); //static B

    }
}

class A{
    public void test1(){
        System.out.println("A  test1");
    }

    public static void test2(){
        System.out.println("static A");
    }
}

class B extends A{
    public void test1(){
        System.out.println("B test1");
    }

    public static void test2(){
        System.out.println("static B");
    }
}

关于instanceof关键字
能否编译通过就是创建对象所在的类与instanceof后面的是否有继承关系
而true和false是由对象右边的具体实例与instanceof后面能否互相转化

public class Test01 {
    public static void main(String[] args) {
        //能否编译通过就是创建对象所在的类与instanceof后面的是否有继承关系
        //而true和false是由对象右边的具体实例与instanceof后面能否互相转化
        Person s1 = new Student();
        System.out.println(s1 instanceof Student); //true
        System.out.println(s1 instanceof Person); //true
        System.out.println(s1 instanceof Teacher); //false
        Student s2 = new Student();
        System.out.println(s2 instanceof Student); //true
        System.out.println(s2 instanceof Person); //true
        
        ((Student)s1).go();  //强制类型转化
    }
}

class Person{

}

class Student extends Person{
    public void go(){
        System.out.println("go");
    }
}

class Teacher extends Person{

}

static关键字 记住在方法区存在 且从属于类 请看下面的代码

public class Test02 {
    static int i = 0;
    {
        //代码块(匿名代码块)
        System.out.println("匿名代码块");
    }
    static {
        //静态代码块
        //类加载的时候执行 只执行一次
        System.out.println("静态代码块");
    }
    public Test02(){
        System.out.println("构造器");
    }
    public static void main(String[] args) {
        Test02 t = new Test02();
        /*
          静态代码块
          匿名代码块
          构造器
          */
        test();
        test();
        System.out.println(i);  //2
    }
    public static void test(){
        i++;
    }
}

抽象类

抽象类用abstract修饰
抽象方法只有方法的名字 没有方法的实现
抽象类可以有普通的方法
类中有抽象方法必须是抽象类
继承抽象类必须要实现它其中所有的抽象方法 除非自己本身是抽象的

public abstract class Action {
    public abstract void doSome();
}

class A extends Action{
    @Override
    public void doSome() {
        System.out.println("doSome");
    }
}

接口

接口就是规范 定义的是一组规则
接口中的方法都是抽象的 public abstract
类可以利用接口实现多继承(伪多继承)
实现类必须实现接口定义的所有方法
请看代码

public interface UserService {
    void add(String name);
    int query(int num);
}
public class UserServiceImpl implements UserService {

    @Override
    public void add(String name) {
        System.out.println("add");
    }
    @Override
    public int query(int num) {
        System.out.println("query");
        return -1;
    }
}

内部类

public class Outer {
    private int id;
    public void out(){
        System.out.println("out");
    }
    class Inner{
        //可以获得外部类私有属性 私有方法
        public void in(){
            id = 10;
            System.out.println(id);
            System.out.println("in");
        }
    }
}
 	public static void main(String[] args) {
        Outer outer = new Outer();
        Outer.Inner inner = outer.new Inner();
        inner.in(); // 10 in
    }

加入static关键字就变成静态内部类 由于程序开始时静态内部类就创建了 故访问不到id

匿名内部类 没有名字的类

public class Test02{
    public static void main(String[] args) {
        UserService user = new UserService() {
            public void hello() {
                System.out.println("Hello");
            }
        };
    }
}
interface UserService{
    void hello();
}
上一篇:SQL常用操作(一)


下一篇:Oracle中trunc()函数用法