首页 > 编程语言 > 详细

Java对象

时间:2021-01-28 17:41:53      阅读:26      评论:0      收藏:0      [点我收藏+]

面向过程和面向对象

面向过程思想

  • 步骤清晰简单,第一步做什么,第二步做什么
  • 面对过程适合处理一些较为简单的问题

面向对象思想

  • 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索
  • 面向对象适合处理复杂的问题,适合处理需要多人协作的问题

对于描述复杂的事物,为了宏观上把握、整体上合理分析,我们需要面向对象的思路来分析整个系统。但是,具体到微观才做,仍然需要面向过程的思想去处理。

什么是面向对象

面向对象编程(Object-Oriented Programming,OOP)

面向对象的本质是:以类的方式组织代码,以对象的组织(封装)数据

三大特性:封装继承多态

  • 从认识论的角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象
  • 从代码运行的角度考虑是先有类,后有对象。类是对象的模板

方法的调用

静态的方法

//和类一起加载的 
public static void a(){}

非静态的方法

//类实例化后才存在  
public void b(){}

形参和实参

public class methodDemo {
    public static void main(String[] args) {
        int result = sum(2,3.14);// 实参与形参的数据类型要对应
    }
    public static int sum(int a, double b) {// 形式参数
        return a + (int)b;
    }
}

值传递

public class Demo02 {
    public static void main(String[] args) {
        int a = 1;
        System.out.println(a);// 打印当前a的值为1
        change(a);// 传入实参a为1,执行change方法后a=10,但并未返回a的值
        System.out.println(a);// 当前a仍为1
    }
    public static void change(int a) {
        a = 10;
    }
}
执行结果:
1
1

引用传递

public class Demo03 {
    public static void main(String[] args) {
        Cat cat1 = new Cat();// 实例化一个Cat类的cat1对象
        System.out.println(cat1.name);
        System.out.println(cat1.sex);
        System.out.println(cat1.age);
        cat1.name = "coco";
        cat1.sex = "公";
        cat1.age = 1;
        System.out.println(cat1.name);
        System.out.println(cat1.sex);
        System.out.println(cat1.age);
        Demo03.change(cat1);
        System.out.println(cat1.name);
        System.out.println(cat1.sex);
        System.out.println(cat1.age);
    }
    public static void change(Cat cat) {
        // cat是一个Cat类的对象(形参),可以改变其属性
        cat.name = "果冻";// cat. 指向的是Cat类的属性--->Cat cat1 = new Cat();
        cat.sex = "母";
        cat.age = 3;
    }
}
/* 定义了一个Cat类,其中有name、sex、age这三个属性 */
class Cat {
    String name;// 默认为null
    String sex;
    int age;// 默认为0
}
执行结果:
null
null
0
coco
公
1
果冻
母
3

this关键字(指代当前类)

注意点:

  1. 静态方法不能调用非静态方法
  2. 静态方法可以调用静态方法
  3. 非静态方法可以调用静态方法和非静态方法

加载的顺序问题:

静态方法是在类加载的时候就创建好了,而非静态方法是伴随着对象的创建才创建

类与对象的关系

  • 类是一种抽象的数据类型,它是对某一事物整体描述/定义,但是不能代表某一个具体的事物

  • 对象是抽象概念的具体实例

创建与初始化对象

  1. 使用new关键字创建对象

  2. 使用new关键字创建对象时,除了分配内存空间,还会给创建好的对象进行默认的初始化以及对类中构造器的调用

  3. 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。

构造器的特点:

  1. 必须和类名相同
  2. 没有返回值,也不能写void

构造器的作用

		1. new本质上是在调用构造器
		2. 初始化对象(属性)的值

注意点:一旦定义了有参构造,如果想使用无参构造,必须显示定义无参构造

构造器快捷键:alt+insert

一个类即使什么都不写,它也会存在一个方法(构造器)

技术分享图片

【演示】

public class Student {
    // 定义属性name、sex、age
    String name;
    String sex;
    int age;
    /* 无参构造 */
    public Student() {
        this.name = "张三";// this关键字指当前类,即Student类
        this.sex = "男";
        this.age = 18;
    }
    /* 有参构造 */
    public Student(String name, String sex, int age) {
        this.name = name;// this.name中的name指的是Student类中的String name,后面的name是传进来的参数
        this.sex = sex;
        this.age = age;
    }
    // 定义方法status
    public void status(String name) {
        if (name == "张三"){
            System.out.println(this.name+"在学习");
        }
        if (name == "李四"){
            System.out.println(this.name+"在睡觉");
        }
    }
}

public class Application {
    public static void main(String[] args) {
        /*
        使用new关键字,其本质是在调用构造器
        所以必须要有构造器
         */
        Student student1 = new Student();// 调用的是无参构造方法
        System.out.println(student1.name);
        System.out.println(student1.sex);
        System.out.println(student1.age);
        Student student2 = new Student("李四", "女", 16);// 调用的是有参构造方法
        System.out.println(student2.name);
        System.out.println(student2.sex);
        System.out.println(student2.age);
        student1.status("张三");
        student2.status("李四");
    }
}
执行结果:
张三
男
18
李四
女
16
张三在学习
李四在睡觉

总结类与对象

  1. 类与对象
    • 类是一个模板,对象是一个具体的实例
  2. 方法
    • 定义、调用
  3. 对应的引用
    • 引用类型:对象是通过引用来操作的:栈—->堆
    • 八大基本类型(byte.short.int.long.float.double.char.boolean)
  4. 对象属性:字段Field,成员变量
    • 默认初始化:
      • 数字: 0 0.0
      • char: u0000
      • boolean: false
      • 引用类型: null
    • 修饰符 属性类型 属性名 = 属性值
  5. 对象的创建和使用
    • 必须使用new关键字创建对象,使用构造器 Person peanut = new Person()
    • 对象的属性 peanut.name
    • 对象的方法 peanut.sleep()
    • 静态的属性 属性
    • 动态的行为 方法

【演示】

public class Pet {
    String name;
    int age;
    public void shut() {
        System.out.println("叫了一声");
    }
}
public class Application {
    public static void main(String[] args) {
        Pet dog = new Pet();
        dog.name = "旺财";
        dog.age = 3;
        dog.shut();
        Pet cat = new Pet();
    }
}

【内存分析】

技术分享图片

封装

封装是将内部信息隐藏,对外暴露接口让使用者去调用

封装的关键

  • 属性私有(private)
  • get/set方法(alt+insert快速生成)

封装的好处

  • 提高了程序的安全性,保护数据
  • 隐藏代码的实现细节
  • 统一接口
  • 系统可维护增加了

【演示】

public class Student {
    /* 属性私有 */
    private String name;// private修饰的变量作用域仅在本类
    private char sex;
    private int age;
    // get 获得这个属性的值
    public String getName() {
        return name;
    }
    // set 给这个属性设置值
    public void setName(String name) {
        this.name = name;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age > 100 || age < 0){
            System.out.println("年龄设置不合法");
        }else{
            this.age = age;
        }
    }
}
public class Application {
    public static void main(String[] args) {
        Student student1 = new Student();
        student1.setName("张三");
        student1.setSex(‘男‘);
        student1.setAge(20);
        System.out.println(student1.getName());
        System.out.println(student1.getSex());
        System.out.println(student1.getAge());
    }
}
执行结果:
张三
男
20

继承

继承的本质是对某一批类的抽象

继承的关键字是 `extends

Java中只有单继承,没有多继承(一个孩子只能有一个亲生父亲,而一个父亲可以有多个孩子)

  • 继承是类与类之间的关系,父类(基类),子类(派生类)
  • 子类和父类之间是有"子类" is a "父类"的关系

【演示】

/* Person类:父类(基类)*/
public class Person {
    private String job; // 这个属性是私有的,其子类不能继承
    public String name = "中国人";// 这个属性是公共的,其子类可以继承
    // 这个方法其子类也可以继承
    public void print() {
        System.out.println("Person");
    }
}
/* Teacher类:子类(派生类)Teacher是一个Person */
public class Teacher extends Person{
    public String name = "张三";
    public void print(String name) {
        System.out.println(name);// 这个name是传进来的参数
        System.out.println(this.name);// 这个name是本类中的name张三
        System.out.println(super.name);// 这个name是父类中的name中国人
    }
    public void print() {
        System.out.println("Teacher");
    }
    public void test() {
        print();// 指本类中的print方法
        this.print();// 指本类中的print方法
        super.print();// 指父类中的print方法
    }
}
public class Application {
    public static void main(String[] args) {
        Teacher teacher = new Teacher();
        teacher.print("李四");
        teacher.test();
    }
}
执行结果:
李四
张三
中国人
Teacher
Teacher
Person

Object

通过看类之间的关系发现(ctrl+h),任何类都会默认继承Object类(Java.lang.Object)

技术分享图片

一个类中即使不写任何语句,也会有可以调用的方法,因为这些类默认继承Object类,所以这些方法都来自Object类

super详解

注意:若Student类继承了Person类,尽管Student类中没有写任何代码,但是Student类继承了Person类中的可继承的属性以及方法,Student类中默认有其无参构造方法且默认其中第一个语句是person类的无参构造方法super(),即Student类中的无参构造方法中包含父类的无参构造方法并且父类的无参构造方法在子类无参构造方法中的第一个语句。

【演示】

/* Person类:父类(基类)*/
public class Person {
    /* 父类无参构造方法 */
    public Person() {
        System.out.println("父类无参构造方法执行");
    }
    /* 父类有参构造方法 */
    public Person(String name) {
        System.out.println(name);
    }
}
/* Student类:子类(派生类)*/
public class Student extends Person{
    public Student() {
        /*
         隐藏代码:super();调用父类的无参构造方法
         注意:这段代码必须在子类无参构造方法的第一句
         */
        //super();
        //super("I love China!");
        System.out.println("子类无参构造方法执行");
    }
}
public class Application {
    public static void main(String[] args) {
        Student student = new Student();//new Student()时会自动调用Student无参构造
    }
}
执行结果:
父类无参构造方法执行
子类无参构造方法执行

【解释】:若父类中只定义了有参构造方法,没有显示定义无参构造方法,那么子类的无参构造方法就会报错:没有默认的构造方法可用。因为子类默认的无参构造方法中的第一条语句时super();(这句代码是隐藏的,默认存在)super()指的是父类的无参构造方法,而父类却没有定义无参构造方法,所以程序会报错。

【解决办法】:(在父类中只定义了有参构造方法,没有显示定义无参构造方法的情况下)

  1. 在父类中定义无参构造方法
  2. 在子类中的无参构造方法中的第一句调用父类的有参构造方法

super注意点

  1. super调用父类构造器,必须放在构造器的第一行
  2. super必须只能出现在子类的方法或者构造器中
  3. super和this不能同时调用构造方法!

this和super的不同点

  1. 代表的对象不同:
    • this:本身调用者这个对象
    • super:代表父类对象的应用
  2. 前提不同:
    • this:在没有继承的前提下也可以使用
    • super:必须存在继承关系
  3. 构造方法不同:
    • this();本类构造器
    • super();父类构造器

重写

重写是方法的重写,需要有继承的关系,子类重写父类的方法

  1. 方法名必须相同
  2. 参数列表必须相同
  3. 修饰符:范围可以扩大但不能缩小 (public > protected > default > private)
  4. 抛出的异常:范围可以缩小但是不能扩大 ClassNotFoundException —> Exception
  5. 返回的类型必须一直与被重写的方法的返回类型相同或其子类

重写,子类的方法和父类的方法必须一致,方法体不同

快捷键:1.alt+insert -->OverrideMethod 2.Ctrl+O

【演示】

public class Dad {
    public void test() {
        System.out.println("Dad-->test");
    }
}
public class Son extends Dad{
    @Override// 重写
    public void test() {
        System.out.println("Son-->test");
    }
}
public class Application {
    public static void main(String[] args) {
        //方法的调用和左边有关,定义的数据类型有关
        Son a = new Son();
        a.test();
        Dad b = new Son();// 父类Dad的引用b指向子类Son
        b.test();// 子类的方法重写了父类的方法
    }
}
执行结果:
Son-->test
Son-->test

多态

即统一方法可以根据发送对象的不同而采取多种不同的方式

一个对象的实际类型是确定的,但是可以指向对象的引用类型有很多

多态存在的条件

  • 有继承关系
  • 子类重写父类的方法
  • 父类的引用指向子类对象

多态的注意事项

  1. 多态是方法的多态,属性没有多态
  2. 父类和子类有关系,类型转换异常
  3. 存在条件:继承关系,方法需要重写,父类引用指向子类对象

static,final,private修饰的方法不能重写

【演示】

public class Person {
    public void run() {
        System.out.println("Person-->run");
    }
}
public class Student extends Person{
    @Override
    public void run() {
        System.out.println("Student-->run");
    }
    public void eat() {
        System.out.println("Student-->eat");
    }
}
public class Application {
    public static void main(String[] args) {
        /*
        * 一个对象的实际类型是确定的
        * new Student();
          new Person();
        */
        Student s1 = new Student();// student可以调用的方法都是自己的或者是父类的
        Person s2 = new Student();// person父类型只能调用自己的方法,不能调用子类特有的方法
        s1.run();
        s1.eat();
        s2.run();// 若子类重写了父类的方法,执行子类的方法
        ((Student)s2).eat();// 若父类型调用子类中特有的方法需要强制转换
    }
}
执行结果:
Student-->run
Student-->eat
Student-->run
Student-->eat

instanceof

System.out.println(X instanceof Y);能不能通过编译,看X与Y是否存在父子关系

【演示】

public class Person {
}
public class Teacher extends Person{
}
public class Student extends Person{
}
public class Application {
    public static void main(String[] args) {
        /*
        父类----->----->---->子类
        Object->String
        Object->Person->Student
        Object->Person->Teacher
         */
        Object obj = new Student();
        System.out.println(obj instanceof Object);// true
        System.out.println(obj instanceof Person);// true
        System.out.println(obj instanceof Student);// true
        System.out.println(obj instanceof Teacher);// false
        System.out.println(obj instanceof String);// false
        Person per = new Student();
        System.out.println(per instanceof Object);// true
        System.out.println(per instanceof Person);// true
        System.out.println(per instanceof Student);// true
        System.out.println(per instanceof Teacher);// false
        //System.out.println(per instanceof String);编译报错
        Student stu = new Student();
        System.out.println(stu instanceof Object);// true
        System.out.println(stu instanceof Person);// true
        System.out.println(stu instanceof Student);// true
        //System.out.println(stu instanceof Teacher);编译报错
        //System.out.println(stu instanceof String);编译报错
    }
}

类型转换问题

低(子类)转高(父类)时,由于子已经继承了父的所有,所以删去属于自己的后自然而然就可以转化为父类的;
高(父类)转低(子类)时,则需要重新开辟只属于子的空间,则需用强制转换

子类转化为父类(向上转型) 子类会丢失自己的方法
父类转化为子类(向下转型 强制转换) 可能会丢失精度或方法

public class Person {
}
public class Student extends Person{
    public void eat() {
        System.out.println("Student->eat");
    }
}
public class Application {
    public static void main(String[] args) {
        Student student = new Student();
        student.eat();
        Person person = student;//Student类型转为Person类型 (低转高)向上转型
        //person.eat();编译报错,丢失了子类自己的方法
        Person p1 = new Person();
        if (p1 instanceof Student){
            Student s1 = (Student) p1;//向下转型,需要强制转换
            ((Student) p1).eat();// 可以调用,但是不能执行,丢失了方法
        }
    }
}

static关键字详解

在类中用static修饰的成员变量称为静态变量,反之则称为非静态类

静态变量与非静态变量的区别

静态变量是属于类的,“可以”使用类名.属性来访问,

非静态变量是属于对象的,“必须”使用对象来访问

public class Test {
    public String name; // 非静态变量
    public static int age;// 静态变量

    private int id;// 非静态变量(私有的)
    private static char sex;// 静态变量(私有的)

    public static void main(String[] args) {
        System.out.println(Test.age);// 静态变量可以使用"类名.属性"来访问
        Test student = new Test();
        System.out.println(student.name);// 非静态变量通过实例对象student来访问
        System.out.println(student.age);// 静态变量也可通过实例对象student来访问

        System.out.println(Test.sex);// 通过类名亦可访问私有静态变量
        System.out.println(student.id);// 通过实例对象student亦可访问私有非静态变量
    }
}

【注意】

  1. 静态变量对于类而言在内存中只有一个,能被类的所有实例共享。实例变量对于类的每个实例都有一份,他们之间互不影响
  2. 在加载类的过程中为静态变量分配内存,实例变量在创建对象时分配内存,所以静态变量可以使用类名来直接访问,而不需要使用对象来访问

static方法

在类中,使用static修饰的方法称为静态方法,反之则称为非静态方法。

静态方法与非静态方法的区别

  1. 静态方法属于类,"可以"使用类名来调用
  2. 非静态方法属于对象,"必须"使用对象来调用
  3. 静态方法不可以访问非静态变量和调用非静态方法,但是”可以”直接访问类中的静态变量和调用静态方法
  4. 非静态方法”可以”直接访问类中的非静态变量和非静态方法,”也可以”直接访问类中的静态变量和静态方法

注意:this和super在类中属于非静态变量(静态方法中不能使用)

public class Test02 {
    public static int a;// 静态变量
    public int b;// 非静态变量
    public static void run() {}// 静态方法
    public void go() {}// 非静态方法

    /*
    静态方法中不可以访问非静态变量和调用非静态方法
    但是可以直接访问类中的静态变量和调用静态方法
     */
    public static void statical() {
        //System.out.println(b);报错
        //go();报错
        System.out.println(a);
        run();
    }
    /*
    非静态方法”可以”直接访问类中的非静态变量和非静态方法
    也可以直接访问类中的静态变量和静态方法
     */
    public void dynamic() {
        System.out.println(b);
        go();
        System.out.println(a);
        run();
    }
}

为什么静态方法中不能访问非静态变量和非静态方法?

静态方法只能调用静态方法(或者变量),非静态方法可以调用静态方法(或者变量)

  • 类的静态成员(变量和方法)属于类本身,在类加载的时候就会分配内存,可以通过类名直接去访问(类名.方法|类名.变量);
  • 非静态成员(变量和方法)属于类的对象,所以只有在类的对象产生(创建类的实例)时才会分配内存,然后通过类的对象(实例)去访问。

在一个类的静态成员中去访问其非静态成员之所以会出错是因为在类的非静态成员不存在的时候类的静态成员就已经存在了,访问一个内存中不存在的东西当然会出错。

子类父类中的static

  1. 父类的静态方法可以被继承,但不能被子类重写
  2. 父类的非静态方法不能被子类重写为静态方法
public class Person {
    public static void go() {
        System.out.println("Person->go");
    }
    public void run() {
        System.out.println("Person->run");
    }
}
public class Student extends Person {
    /* 子类不能重写父类的静态方法
    @Override
    public void go() {
        super.go();
    }
     */

    /* 不能将父类的非静态方法重写为静态方法
    @Override
    public static void run() {
        super.run();
    }
     */
}
public class Application {
    public static void main(String[] args) {
        Student student = new Student();
        student.go();// 子类可以继承父类的静态方法
    }
}

代码块和静态代码块

类中可以编写代码块(匿名代码块)和静态代码块

匿名代码块和静态代码块的执行

  • 因为没有名字,在程序中并不能主动调用这些代码块
  • 匿名代码块是在创建对象的时候自动执行的,并且在构造器执行之前。同时匿名代码块在每次创建对象的时候都会自动执行
  • 静态代码块是在类加载完成之后自动执行,并且只执行一次

注:每个类在第一次被使用的时候就会被加载,并且一般只加载一次

public class Test01 {
    {
        System.out.println("匿名代码块");
    }
    static {
        System.out.println("静态代码块");
    }

    public Test01() {
        System.out.println("构造方法");
    }

    public static void main(String[] args) {
        Test01 test1 = new Test01();
        Test01 test2 = new Test01();
        Test01 test3 = new Test01();
    }
}
执行结果:
静态代码块
匿名代码块
构造方法
匿名代码块
构造方法
匿名代码块
构造方法

匿名代码块和静态代码块的作用

  • 匿名代码块的作用是给对象的成员变量初始化赋值,但是因为构造器也能完成这项工作,所以匿名代码块用的很少
  • 静态代码块的作用是给类中的静态成员变量初始化赋值
public class Test02 {
   public static String name;
   static {
       name = "张三";
   }

    public Test02() {
       name = "李四";
    }
    public static void main(String[] args) {
        System.out.println(Test02.name);
        Test02 test = new Test02();
        System.out.println(test.name);
    }
}
执行结果:
张三
李四

注:在构造器中给静态变量赋值,并不能保证赋值成功,因为构造器执行是在创建对象之后才指向,但是静态变量可以不创建对象而直接使用类名来访问

创建和初始化对象的过程

Student s1 = new Student();
  1. 加载类,并初始化静态属性
  2. 执行静态代码块
  3. 分配内存空间,同时初始化类中非静态属性的值
  4. 执行Student父类构造器
  5. 对Student中的非静态属性显式赋值(如果有的话)
  6. 执行匿名代码块
  7. 执行构造器
  8. 返回内存地址

抽象类

abstract修饰符可以用来修饰方法也可以用来修饰类,如果修饰方法,那么该方法就是抽象方法;如果用来修饰类,那么该类就是抽象类。

抽象类和抽象方法的关系:抽象类中可以没有抽象方法,但有抽象方法的类必须是抽象类!

语法

声明类的同时,加上abstract修饰符就是抽象类
声明方法的同时,加上abstract修饰符,并且去掉方法的大括号,同时结尾加上分号,该方法就是抽象方法

public abstract class Aciton{
    public abstract void doSomething();
}
public void doSomething(){...}

对于普通方法来讲:
‘public void doSomething()’这部分是方法的声明,‘{…}’是方法的实现,如果大括号里面什么都没有就是空实现

特点及作用

抽象类,不能使用new关键字来创建对象,它是用来让子类继承的
抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的

子类继承抽象类后,需要实现抽象类的所有未实现的抽象方法,否则这个子类也要声明为抽象类

public abstract class Action {
    public abstract void doSomething();
    public void shut() {
        System.out.println("shut");
    }
}
public class Eat extends Action {
    public void doSomething() {
        System.out.println("eat");
    }
}
public class Test {
    public static void main(String[] args) {
        //Action action = new Action();报错,抽象类不能new对象
        Action eat = new Eat();
        eat.doSomething();
        eat.shut();
    }
}
执行结果:
eat
shut

接口

接口:只有规范(方法的声明)

  • 普通类:只有具体实现
  • 抽象类:有具体实现和规范(抽象方法)

接口中的方法都是抽象方法(public abstract修饰),接口的变量都是静态常量(public static final修饰)

接口和抽象类的区别

相同点

  1. 不能被实例化(不能new)
  2. 接口的实现类或抽象类的子类都只有实现了接口或抽象类中的方法后才能实例化

不同点

  1. 接口只有定义,不能有方法的实现,而抽象类可以有定义与实现,方法可在抽象类中实现
  2. 实现接口的关键字为implements,继承抽象类的关键字为extends。一个类可以实现多个接口,但一个类只能继承一个抽象类。所以,使用接口可以间接地实现多重继承
  3. 接口强调特定功能的实现,而抽象类强调所属关系
  4. 接口成员变量默认为public static final,必须赋初值,不能被修改;其所有的成员方法都是public abstract的。抽象类中成员变量默认default,可在子类中被重新定义,也可被重新赋值;抽象方法被abstract修饰,不能被private、static、synchronized和native等修饰,必须以分号结尾不带大括号
  5. 接口被用于常用的功能,便于日后维护和添加删除,而抽象类更倾向于充当公共类的角色,不适用于日后重新对立面的代码修改。功能需要累积时用抽象类,不需要累积时用接口

【演示】

public interface UserService {
    // 所有的常量默认都是public static final修饰的
    int AGE = 20;
    // 所有方法默认都是public abstract修饰的
    void add();
    void delete(String name);
}
public interface TimeService {
    void timer();
}
public class UserServiceIpl implements UserService, TimeService{
    /*
    一个类可以实现多个接口
    UserServiceIpl中需重写UserService, TimeService中所有声明的方法
     */
    @Override
    public void add() {
        System.out.println("aaaaa");
    }

    @Override
    public void delete(String name) {
        System.out.println(name);
    }

    @Override
    public void timer() {
        System.out.println("ccccc");
    }

    public static void main(String[] args) {
        UserServiceIpl test1 = new UserServiceIpl();
        test1.add();
        test1.delete("bbbbb");
        test1.timer();
        UserService test2 = new UserServiceIpl();
        // test2只能调用UserService中声明的方法及Object中的方法
        test2.add();
        test2.delete("bbbbb");
        TimeService test3 = new UserServiceIpl();
        // test3只能调用TimeService中声明的方法及Object中的方法
        test3.timer();
    }
}

【扩展:一个接口继承多个接口】

public interface A {
    void add();
}
public interface B {
    void delete();
}
/* 接口X把接口A接口B中的方法都继承了 */
public interface X extends A, B{
    void test();
}
/* Demo相当于实现了A、B、X三个接口 */
public class Demo implements X{
    @Override
    public void add() {

    }

    @Override
    public void delete() {

    }

    @Override
    public void test() {

    }
}

各种内部类

成员内部类

【演示】

public class Outer {
    private int id = 110;
    public void shut() {
        System.out.println("这是外部类的方法");
    }
    public class Inner {
        public void method() {
            System.out.println("这是内部类的方法");
            System.out.println(id);// 调用外部类中的私有变量
            shut();// 调用外部类的方法
        }
    }
}
public class Application {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.shut();
        Outer.Inner inner = outer.new Inner();// 通过Outer实例化内部类Inter
        inner.method();
    }
}

静态内部类

【演示】

public class Outer {
    private int id = 110;
    public void shut() {
        System.out.println("这是外部类的方法");
    }
    public static class Inner {
        public void method() {
            System.out.println("这是内部类的方法");
            //System.out.println(id);报错 不能调用静态外部类中的属性
            //shut();报错 不能调用静态外部类的方法
        }
    }
}
public class Application {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.shut();
        /*
        Outer.Inner inner = outer.new Inner();报错
        Inner是静态类类会先加载,实例化Inner时需要借助外部类,但是外部类还没有被实例化
         */
    }
}

局部内部类

【演示】

public class Outer {
    public void test() {
        class inner {
            public void method() {
                System.out.println("这是局部内部类的方法");
            }
        }
        inner inner = new inner();// 在外部类的方法中实例内部类
        inner.method();
    }
}
public class Application {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.test();
    }
}
执行结果:
这是局部内部类的方法

匿名内部类

【演示】

public class Demo {
    public static void main(String[] args) {
        new Person().run();// 实例对象没有定义名字,称为匿名
        new Person().shut();
        /* 匿名内部接口 */
        new UserService() {
            @Override
            public void add() {
                System.out.println("++++");
            }
        };
    }
}
class Person {
    public void run() {
        System.out.println("Person->run");
    }
    public void shut() {
        System.out.println("Person->shut");
    }
}
interface UserService {
    void add();
}

Java对象

原文:https://www.cnblogs.com/jin99/p/14339147.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!