7、Java入门教程【面向对象】

面向对象是Java编程的核心概念,如果不能充分了解面向对象的思想,那么会给你在实际的项目开发过程中,带来很多业务设计上的困扰。

一、构造器

我们在设计完一个类,在使用这个类去创建对象实例的时候,有些场景是需要对实例做初始化操作的,那么Java中提供了构造器来满足这方面要求。

1、原则

  • 名字必须与所在类名称一致
  • 不能有返回值和返回值类型
  • 构造器也可以重载(参数列表不一样)
  • 类在设计时,如果没有写构造器,Java是会为类自动生成一个无参数构造器。
  • 如果定义类的有参数构造器,则不会创建无参数构造器。【建议手动创建一个无参数构造器】

2、 构造器的多种形式

默认无参数构造器:

class Rock{
	printme(){
		System.out.print("printme");
	}
}

Rock r=new Rock();

有参数构造器:

class Rock {
    Rock(String name) {
        System.out.print("这是一个有参构造器:" + name);
    }
}
Rock r = new Rock("IT飞牛");
//这是一个有参构造器:IT飞牛

构造器重载:

class Rock {
    Rock(String name) {
        System.out.println("这是一个有参构造器,姓名:" + name);
    }

    Rock(String name, int age) {
        this(name);//这里使用this调用其他构造器,复用
        System.out.println("这是一个有参构造器,年龄:" + age);
    }
}

Rock r = new Rock("IT飞牛", 18);

//这是一个有参构造器,姓名:IT飞牛
//这是一个有参构造器,年龄:18

二、重载

类中的一个方法,有些场景下需要根据不同的情况,做不同的操作,当然我们可以直接定义不同的方法就能实现。但是有些时候的确是同类型的操作,方法名最好是一样的,这时候我们可以使用重载来实现。

类中的重载主要是根据方法传入的参数类型列表,去自动识别调用不同的方法执行。

下面提供了同方法名,但是不同参数的案例:

package com.itfeiniu.hello;

public class HelloWorld {
    public static void main(String[] args) {
        Rock r = new Rock();
        r.say();
        r.say("你好");
        r.say("你好", 3);
        r.say(3, "你好");
    }
}

class Rock {
    void say() {
        System.out.println("啥都没说");
    }

    void say(String msg) {
        System.out.println("说:" + msg);
    }

    void say(String msg, int num) {
        System.out.println(msg + ",被说了" + num + "遍");
    }

    void say(int num, String msg) {
        System.out.println("说了" + num + "遍," + msg);
    }
}
//啥都没说
//说:你好
//你好,被说了3遍
//说了3遍,你好

可以看到,不同的入参,调用了不同的同名方法。

涉及基本类型的重载,可能会由于变量类型提升,调用的方法有偏差。例如:Rock加入有个do方法,调用r.do(1)这个方法,参数会按照int类型去识别。请看下面案例:“

package com.itfeiniu.hello;

public class HelloWorld {
    public static void main(String[] args) {
        Rock r = new Rock();
        r.say(2);
        r.say((byte) 2);
    }
}

class Rock {
    void say(byte num) {
        System.out.println("这是byte");
    }

    void say(int num) {
        System.out.println("这是int");
    }

}
//这是int
//这是byte

三、this关键字

this就是一个变量,可以用在方法中,来拿到当前对象。

接触过js的小伙伴应该是比较好理解,java中的this的指向和js中的this的指向是一个原则:【谁调用,this就指向谁】

四、static的含义

使用static final修饰的成员变量就被称为常量。

1、静态属性和方法

  • static方法是没有this的,在static方法内部不能调用this。并且在static内部不能调用非静态方法。
  • 在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途,他很像全局方法。
  • static修饰,属于类,在计算机里只有一份,会被类的全部对象共享。
  • 静态成员在类被加载时就被初始化,不需要创建类的实例。
  • 静态成员被所有实例共享,可以用来存储类级别的信息。
package com.itfeiniu.hello;
public class Food {
    String name;	//这是每个Food实例的变量,每个实例都有独立的一个name属性。
    static int num;	//这是Food类的变量,所有类的实例共享一个变量。
}

2、静态代码块

使用static定义的代码块称为静态代码块。一般用于初始化静态成员变量

public class Student {
    public String id;
    public String name;
    public static String major;

    static {
        major = "软件工程";
        System.out.println("执行了 静态代码块");
    }
}
  • 静态代码块不管生成多少个对象,其只会执行一次
  • 如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次合并
public class Demo {
    private static int x = 1;
    private int y = 2;

    static {
        System.out.println("静态代码块1,x=" + x);
        x = 10;
    }

    {
        System.out.println("实例代码块1,x=" + x + ", y=" + y);
        y = 20;
    }

    public Demo() {
        System.out.println("构造函数,x=" + x + ", y=" + y);
        y = 30;
    }

    static {
        System.out.println("静态代码块2,x=" + x);
        x = 100;
    }

    {
        System.out.println("实例代码块2,x=" + x + ", y=" + y);
        y = 40;
    }
    public static void main(String[] args) {
        Demo demo1 = new Demo();
        Demo demo2 = new Demo();
    }
}

7、Java入门教程【面向对象】_第1张图片

五、封装

合理隐藏 合理暴露

1、访问控制

java类中的方法或者属性,可以设置访问范围,修饰符是:privateprotectpublic

  • private:该成员可以被该类内部成员访问;

  • default:该成员可以被该类内部成员访问,也可以被同一包下其他的类访问;

  • protected:该成员可以被该类内部成员访问,也可以被同一包下其他的类访问,还可以被它的子类访问;

  • public:该成员可以被任意包下,任意类的成员进行访问。

2、读写拦截器getter、setter

java中的读写拦截器是基于public方法来实现的。

package com.itfeiniu.hello;

public class HelloWorld {
    public static void main(String[] args) {
        Rock r = new Rock();
        r.setName("张三");
        System.out.println(r.getName());
        r.setAge(20);
        System.out.println(r.getAge());
    }
}

class Rock {
    private String name;

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    private int age;

}
//张三
//20

可以使用IDEA快速生成gettersetting,如下图:

7、Java入门教程【面向对象】_第2张图片.7、Java入门教程【面向对象】_第3张图片

六、实体类

实体类的特点:

  1. 这个类中的成员变量都要私有,并且要对外提供相应的getXxx,setXxx方法。
  2. 类中必须要有一个公共的无参的构造器。

下面Student类就是典型的实体类,整个类就是用来保存学生数据的,没有其他任何数据处理业务。一般实体类会配合实体类的操作类来使用,实体类存放数据,操作类StudentOperator使用实体类的数据做数据处理业务。

代码如下:

package com.itfeiniu.hello;

public class HelloWorld {
    public static void main(String[] args) {
        Student std1 = new Student("张三", 60);
        StudentOperator sto1 = new StudentOperator(std1);
        sto1.printPass();

        Student std2 = new Student("李四", 50);
        StudentOperator sto2 = new StudentOperator(std2);
        sto2.printPass();
    }
}

class StudentOperator {
    private Student student;

    public StudentOperator(Student student) {
        this.student = student;
    }

    public void printPass() {
        if (student.getScore() >= 60) {
            System.out.println(student.getName() + ",及格了");
        } else {
            System.out.println(student.getName() + ",没及格");
        }
    }
}

class Student {
    private String name;
    private int score;

    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }

    public Student() {
    }

    public String getName() {
        return name;
    }

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

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }
}

七、继承

继承是实现软件复用的重要手段。

1、extends和implements

继承中最常使用的两个关键字是 extendsimplements 。通过使用这两个关键字,我们能实现一个对象获取另一个对象的属性。

所有 Java 的类均是由 java.lang.Object 类继承而来的,所以 Object 是所有类的祖先类,而除了 Object 外,所有类必须有一个父类。

public interface Animal {}

public class Mammal implements Animal{
}

public class Dog extends Mammal{
}

Java不支持多继承,例如下面的写法是错误的:

public class extends Animal, Mammal{} 

但是我们可以用接口来实现(多继承接口来实现),代码结构如下:

//Apple.java
package com.itfeiniu.hello;

class Fruit {
    String color;
    int kg;
    String shape;
}

interface Fruit1 {
    public void eat1();

    public void travel1();
}

interface Fruit2 {
    public void eat2();

    public void travel2();
}

public class Apple extends Fruit implements Fruit1, Fruit2 {
    public Apple(String color, int kg, String shape) {
        this.color = color;
        this.kg = kg;
        this.shape = shape;
    }

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

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

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

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

//helloworld.java
package com.itfeiniu.hello;

public class HelloWorld {
    public static void main(String[] args) {
        Apple app = new Apple("red", 5, "circle");
        app.eat1();
        app.eat2();
        System.out.println(app.color);
    }
}
//eat1
//eat2
//red

八、抽象类

抽象类总结规定:

  1. 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。

  2. 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。

  3. 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。

  4. 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。

  5. 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。

1、抽象方法

如果一个类包含抽象方法,那么该类必须是抽象类。

public abstract void Test{
    public abstract void func();
}

2、抽象类

继承抽象类的子类必须重写父类所有的抽象方法。否则,该子类必须声明为抽象类。

最终,必须有子类实现该父类的抽象方法,否则,从最初的父类到最终的子类都不能创建对象从而失去意义。

package com.itfeiniu.hello;

public abstract class Food {
    public abstract void print();
}

class Apple extends Food {
    @Override
    public void print() {
        System.out.println("我是一个苹果");
    }
}

class Test {
    public static void main(String[] args) {
        Apple a = new Apple();
        a.print();
    }
}
//我是一个苹果

继承抽象类的子类必须重写父类所有的抽象方法!

抽象类中不一定包含抽象方法,但是有抽象方法的类一定是抽象类(不包含抽象方法的抽象类,目的就是不想让调用者实例化该对象,通常用于某些特殊的类的结构设计)。

九、接口

1、接口与类的区别

  • 接口不能用于实例化对象。
  • 接口没有构造方法。
  • 接口中所有的方法必须是抽象方法,Java 8 之后 接口中可以使用 default 关键字修饰的非抽象方法。
  • 接口不能包含成员变量,除了 static 和 final 变量。
  • 接口不是被类继承了,而是要被类实现。
  • 接口支持多继承。

2、接口特性

  • 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。
  • 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)。
  • 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。

3、抽象类和接口的区别

  • 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
  • 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
  • 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
  • 一个类只能继承一个抽象类,而一个类却可以实现多个接口。

4、接口的声明

[可见度] interface 接口名称 [extends 其他的接口名] {
        // 声明变量
        // 抽象方法
}
/* 文件名 : NameOfInterface.java */
import java.lang.*;
//引入包
 
public interface NameOfInterface
{
   //任何类型 final, static 字段
   //抽象方法
}

5、接口的实现

当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类。

类使用implements关键字实现接口。在类声明中,Implements关键字放在class声明后面。

实现一个接口的语法,可以使用这个公式:

...implements 接口名称[, 其他接口名称, 其他接口名称..., ...] ...

6、接口实例

package com.itfeiniu.hello;

interface Food {
    String SCHOOL_NAME = "IT飞牛";

    default void print1() {
        this.print2();
    }

    private void print2() {
        System.out.println("这里是私有方法print2");
    }

    public static void print3() {
        System.out.println("这里是静态方法print3");
    }

    void print4();
}

class Apple implements Food {
    @Override
    public void print4() {
        System.out.println("我是一个苹果," + this.SCHOOL_NAME);
    }
}

class Test {
    public static void main(String[] args) {
        Apple a = new Apple();

        a.print1();
//        a.print2(); 报错
        Food.print3();
        a.print4();
    }
}
//这里是私有方法print2
//这里是静态方法print3
//我是一个苹果,IT飞牛

7、多继承

package com.itfeiniu.hello;

interface A {
    void test1();
}

interface B {
    void test2();
}

//方式一
//interface C extends A, B {
//    //这里实现接口多继承
//}

//class Food implements C {
//
//    @Override
//    public void test1() {
//
//    }
//
//    @Override
//    public void test2() {
//
//    }
//}

//方式二
class Food implements A,B{

    @Override
    public void test1() {

    }

    @Override
    public void test2() {

    }
}

需要注意的是,多继承时,需要确保父接口中不存在同名方法。如果存在同名方法,那么默认会报错,需要在自身类中重写这个同名的方法。

一个类同时继承一个父类并且实现一个或多个接口,如果父类和接口中存在同名方法,那么优先会继承父类中的同名方法,例如:

package com.itfeiniu.hello;

interface A {
    public static void test1() {
        System.out.println("这里是静态方法test1");
    }
}

class D {
    public void test1() {
        System.out.println("这里是test1方法");
    }
}

public class Food extends D implements A {
    public void run() {
        this.test1();
    }
}

class HelloWorld2 {
    public static void main(String[] args) {
        Food f = new Food();
        f.run();
    }
}
//这里是test1方法

十、内部类

1、成员内部类

package com.itfeiniu.hello;

public class Food {
    public static void main(String[] args) {
        Outer.Inner in = new Outer().new Inner();
        in.test();
        //77
		//88
		//99
    }
}

class Outer {
    private int age = 99;

    class Inner {
        private int age = 88;

        public void test() {
            int age = 77;
            System.out.println(age);
            System.out.println(this.age);
            System.out.println(Outer.this.age);
        }
    }
}

2、静态内部类

package com.itfeiniu.hello;

public class Food {
    public static void main(String[] args) {
        Outer.Inner in = new Outer.Inner();
        in.test();
    }
}

class Outer {
    private int age;
    public static String SchoolName="IT飞牛学院";

    public static class Inner {
        private String name;
        public static int a;

        public void test() {
            System.out.println(SchoolName);
//            System.out.println(age);//报错
        }
    }

    public static void test2() {
        System.out.println(SchoolName);
//        System.out.println(age); //静态方法不能访问实例对象
    }
}
//IT飞牛学院

可以直接访问外部类的静态成员,不能直接访问

3、匿名内部类【重要】

就是以中国特殊的局部内部类;所谓匿名,指的就是不需要位这个类声明名字。

package com.itfeiniu.hello;

public class HelloWorld {
    public static void main(String[] args) {
        Animal animal = new Animal() {
            @Override
            public void cry() {
                System.out.println("喵喵");
            }

            @Override
            public void eat() {
                System.out.println("我吃猫粮");
            }
        };
        animal.cry();
        animal.eat();
    }
}

abstract class Animal {
    public abstract void cry();

    public abstract void eat();
}
//喵喵
//我吃猫粮

匿名内部类作为方法入参:

package com.itfeiniu.hello;

public class HelloWorld {
    public static void main(String[] args) {
        go(new Animal() {
            @Override
            public void cry() {
                System.out.println("喵喵");
            }
        });
//        相同效果
//        Animal animal = new Animal() {
//            @Override
//            public void cry() {
//                System.out.println("喵喵");
//            }
//        };
//        go(animal);
    }

    public static void go(Animal a) {
        a.cry();
    }
}

interface Animal {
    public abstract void cry();

}
//喵喵

一个窗口应用程序中,匿名内部类的应用:

package com.itfeiniu.hello;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class HelloWorld {
    public static void main(String[] args) {
        //1、创建窗口
        JFrame win = new JFrame("登录界面");
        JPanel panel = new JPanel();
        win.add(panel);

        JButton btn = new JButton("登录");
        panel.add(btn);

        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(win, "登录一下");
            }
        });
        //用兰姆达表达式替代,效果同上
//        btn.addActionListener(e -> JOptionPane.showMessageDialog(win, "登录一下"));

        win.setSize(400, 400);
        win.setLocationRelativeTo(null);
        win.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        win.setVisible(true);
    }
}

7、Java入门教程【面向对象】_第4张图片

7、Java入门教程【面向对象】_第5张图片

十一、关键字

1、super

可以通过 super 关键字来实现对父类成员的访问,用来引用当前对象的父类。

2、final

  • final修饰类,类不能被继承

    final class A{
        public final void
    }
    //class B extend A{}
    
  • final修饰方法,方法不能被重写

    class C{
        public final void test(){}
    }
    class D extends C{
        //@override
        //public void test(){}
    }
    
  • final修饰变量,总规则:有且仅能赋值一次

    class Test{
        public static void main(String[] args){
            final int a;
            a=12;
            //a=13; 再次赋值时报错
            
            final int[] arr={11,22,33};
            arr[1]=222;//这是可以的
            //arr={22,33};//报错
        }
    }
    
  • 使用static final修饰的成员变量就被称为常量

    //通常用于记录系统的配置信息
    public class Constant{
        public static final String SCHOOL_NAME="IT飞牛";
    }
    

十二、枚举

你可能感兴趣的:(JAVA,java)