Java SE 3rd day:Object

编程入门 行业动态 更新时间:2024-10-23 11:32:18

Java <a href=https://www.elefans.com/category/jswz/34/1758461.html style=SE 3rd day:Object"/>

Java SE 3rd day:Object

(材料源于网络)

Java SE 3rd day:Object-oriented 02

1、本次课程知识点

1、引用数据的操作深入;

2、this关键字的使用;

3、对象数组的概念及操作;

4、引用的实际问题分析;

2、具体内容

2.1 引用数据类型的回顾(重点)

下面编写三道题目,通过题目来简单的对引用传递的操作作一个回顾。

范例:第一道引用范例

class MyReasult {

    private int num = 10;

 

    public void setNum(int n) {

       num = n;

    }

 

    public int getNum() {

       return num;

    }

}

 

public class StringDemo {

    public static void main(String args[]) {

       MyReasult mr = new MyReasult();

       mr.setNum(100);

       fun(mr);

       System.out.println(mr.getNum());

    }

 

    public static void fun(MyReasult temp) {

       temp.setNum(30);

    }

}

30

下面通过内存关系图进行分析,在分析之前再一次回顾一下概念:

● 堆内存:保存的是对象的属性信息;

● 栈内存:保存的是一块堆内存的操作地址;

本程序是一个标准的引用传递操作,即:一块堆内存空间被两块栈内存所指向。

范例:第二道引用范例

    public static void main(String args[]) {

       String mr ="Hello";

       fun(mr);

       System.out.println(mr);

    }

 

    public static void fun(String temp) {

       temp="MLDN";

    }

Hello

本题目的解决关键有一点:字符串的内容不可改变,改变的是内存地址的指向,所以对于String而言最方便的理解是按照一个普通的数字传递那样理解。

package course_2;

 

class MyReasult {

    private String msg = "Hello";

 

    public void setMsg(String m) {

       msg = m;

    }

 

    public String getMsg() {

       return msg;

    }

}

 

public class StringDemo {

    public static void main(String args[]) {

       MyReasult mr = new MyReasult();

       mr.setMsg("World");

       fun(mr);

       System.out.println(mr.getMsg());

    }

 

    public static void fun(MyReasult temp) {

       temp.setMsg("MLDN");

    }

}

MLDN

本程序的问题解决思路与第一道题完全一样,但是这个题目的内存关系图有两种画法:

第一种:简单理解,与第一道思路一样。

第二种:完整画法

String本身就是一个对象,所以理论上应该也有自己的内存分配,于是现在的内存分配如下:

而且String是引用类型,但是对于String的理解可以简单的按照基本数据类型那样,所以以上的完整的内存图表示,只是作为参考,严格来讲,现在的程序就相当于是引用的引用。

2.2 this关键字(重点)

在整个java之中,this关键字是一个最难理解的关键字,this有三种用处:表示属性、表示方法、表示当前对象。

2.2.1 表示属性

在之前的代码中可以发现,可以通过构造方法或者是setter方法为类中的属性赋值,但是,如果说现在代码写成如下的形式:

class Person {

    private String name;

    private int age;

 

    public Person(String a, int n) {

       name = a;

       age = n;

    }

 

    public String getInfo() {

       return "Name: " + name + ",age: " + age;

    }

}

 

public class StringDemo {

    public static void main(String args[]) {

       Person per = new Person("Jones", 30);

       System.out.println(per.getInfo());

    }

}

Name: Jones,age: 30

此时的构造方法,是希望传入两个属性的内容,但是这个构造方法的参数名称并不明确,因为字母“a”和“n”都没有任何的意义,所以现在希望修改构造方法的参数,与类中的属性同名。

    public Person(String name, int age) {

       name = name;

       age = age;

    }

Name: null,age: 0

这个时候构造方法上的确是可以清楚的知道要传递的是name和age的信息,但是最后的结果并没有真正的将传入的name和age两个属性赋予类中的name和age属性,在程序的开发之中,是以“{}”为界,存在一种称为就近原则,因为这个原则,所以之前构造方法中出现的name和age两个参数都是构造方法的参数,与类中的属性没有关系,所以,如果现在想要明确的表示操作的是类中属性的话,则可以使用“this”属性的操作形式。

class Person {

    private String name;

    private int age;

 

    public Person(String name, int age) {

       this.name = name;

       this.age = age;

    }

 

    public String getInfo() {

       return "Name: " + this.name + ",age: " + this.age;

    }   //此处的name和age可加可不加this

}

 

public class StringDemo {

    public static void main(String args[]) {

       Person per = new Person("Jone", 30);

       System.out.println(per.getInfo());

    }

}

Name: Jone,age: 30

建议:在以后的开发之中,方法里面肯定会有参数,也会使用到类中的属性,为了更好的区分,以后只要是类中的属性都必须子在前面加上“this”。

2.2.2 调用方法

如果现在想明确的表示出调用的是本类中方法的话,则使用“this.方法()”的形式,但是对于方法的调用在java中分为两种:一种是普通方法,另外一种就是构造方法。

如果现在希望在一个类中完成构造方法的互调用,则可以使用“this.()”的操作形式,里面可以根据需要传递进若干个参数。

范例:现在类中有三个构造方法,但是这三个构造方法不管调用哪一个,都要执行一段固定的输出“一个新的实例化对象产生”,那么如果说现在按照之前的做法,则代码实现如下:

class Person {

    private String name;

    private int age;

 

    public Person() {

       System.out.println("A new object of Person produce.");

    }

 

    public Person(String name) {

        System.out.println("A new object of Person produce.");

       this.name = name;

    }

 

    public Person(String name, int age) {

       System.out.println("A new object of Person produce.");

       this.name = name;

       this.age = age;

    }

 

    public String getInfo() {

       return "Name: " + this.name + ",age: " + this.age;

    }

}

 

public class StringDemo {

    public static void main(String args[]) {

       Person per = new Person("Jone", 30);

    }

}

A new object of Person produce.

但是,以上的实现手段存在了重复代码。所以使用传统的方法不好使,那么使用this完成。

class Person {

    private String name;

    private int age;

 

    public Person() {

       System.out.println("A new object of Person produce.");

    }

 

    public Person(String name) {

       this();            //调用本类的无参构造

       this.name = name;

    }

 

    public Person(String name, int age) {

       this(name);       //调用有一个参数的构造

       this.age = age;

    }

 

    public String getInfo() {

       return "Name: " + this.name + ",age: " + this.age;

    }

}

 

public class StringDemo {

    public static void main(String args[]) {

       Person per = new Person("Henry",58);

    }

}

A new object of Person produce.

以上的程序是完成了this调用构造的操作形式,但是也同时存在以下的几个注意点:

● 使用this调用构造方法的操作,只能在类中的构造方法的首行;

● 【关键】一个类中虽然可以使用this进行构造方法的互调用,但是一定要保留一个构造方法,是不使用this调用的,以作为程序的出口;

范例:错误的操作

    public Person() {

        this("",0);       //调用两个参数的构造

       System.out.println("A new object of Person produce.");

    }

    public Person(String name) {

       this();          //调用无参的构造

       this.name = name;

    }

    public Person(String name, int age) {

       this(name);      //调用一个参数的构造

       this.age = age;

    }

很明显,可以发现本程序的问题,所以编译器的话也可以自动为用户解决,直接报错。

错误:“recursive construction invocation”,递归构造调用;

2.2.3 表示当前对象

所谓的当前对象指的是当前正在调用类中方法的对象,为了解释此概念,下面先观察这样的一个程序:

package course_2;

 

class Person {

}

 

public class StringDemo {

    public static void main(String args[]) {

       Person per1 = new Person();

       Person per2 = new Person();

       Person per3 = new Person();

       System.out.println(per1); // 直接打印对象

       System.out.println(per2);

       System.out.println(per3);

    }

}

course_2.Person@51cfc277

course_2.Person@1ee83c97

course_2.Person@20e1ed5b

现在的程序是直接输出了对象的信息“”,默认情况下是一串地址信息,所以默认的对象打印就是地址信息,不同的实例化对象地址信息也肯定不一样。

package course_2;

 

class Person {

    public void print() {

       System.out.println("Person this= " + this);

    }

}

 

public class StringDemo {

    public static void main(String args[]) {

       Person per1 = new Person();

       Person per2 = new Person();

       System.out.println("MAIN= " + per1); // 直接打印对象

       per1.print();

       System.out.println("MAIN= " + per2);

       per2.print();

    }

}

MAIN= course_2.Person@50a6023a

Person this= course_2.Person@50a6023a

MAIN= course_2.Person@42dc5733

Person this= course_2.Person@42dc5733

那么之前的“this.属性”严格来讲,含义应该表示成“当前对象的属性”,分析下面一道比较复杂的题目:

package course_2;

 

class A {

    private B var;

 

    public A() { // 2、执行此构造方法

       this.var = new B(this); // 3、实例化B类对象,this=a;

       this.var.get(); // 6、通过B类对象var调用类的get()方法

    }

 

    public void print() { // 8、执行输出

       System.out.println("Hello World. ");

    }

}

 

class B {

    private A temp;

 

    public B(A temp) { // 4、执行此构造,这个时候的temp就是a

       this.temp = temp; // 5、将外部的a的实例给了B的temp属性

    }

 

    public void get() {

       this.temp.print(); // 7、此方法通过A的对象temp调用A的print()方法

    }

}

 

public class StringDemo {

    public static void main(String args[]) {

       A a = new A(); // 1、调用构造方法

    }

}

Hello World.

本题目的:this在任何情况下都表示当前对象。

 

2.2.4 思考题

编写一个公司员工类:Employee,类的组成如下:

● 数据成员:员工号、姓名、薪水、部门

● 操作方法:

|- 利用构造方法完成设置信息:

A、单参,只传递员工号,则员工姓名:无名氏,薪水:0,部门:未定

B、双参,传递员工号,姓名,则员工薪水为 1000,部门:后勤

C、四参,传递员工号,姓名,部门,薪水

D、无参,则均为空值

|- 显示信息

|- 提示:暂时不用编写setter、getter

DIY

package course_2;

 

class Employee {

    private int empno;

    private String ename;

    private int sal;

    private String dept;

 

    public Employee() {

       this.empno = 0;

       this.ename = null;

       this.sal = 0;

       this.dept = null;

    }

 

    public Employee(int empno) {

       this.empno = empno;

       this.ename = null;

       this.sal = 0;

       this.dept = "未定";

    }

 

    public Employee(int empno, String ename) {

       this.empno = empno;

       this.ename = ename;

       this.sal = 1000;

       this.dept = "后勤";

    }

 

    public Employee(int empno, String ename, int sal, String dept) {

       this.empno = empno;

       this.ename = ename;

       this.sal = sal;

       this.dept = dept;

    }

 

    public void printInfo() {

       System.out.println(empno + "  " + ename + "  " + sal + "  " + dept);

    }

}

 

public class StringDemo {

    public static void main(String args[]) {

       Employee emp = new Employee(10, "Henry", 2400, "Seller");

       emp.printInfo();

    }

}

10  Henry  2400  Seller

Answer

package course_2;

 

class Employee {

    private int empno;

    private String ename;

    private double sal;

    private String dept;

 

    public Employee() {

    }

 

    public Employee(int empno) {

       this(empno, "无名氏", 0.0, "未定");

    }

 

    public Employee(int empno, String ename) {

       this(empno, ename, 1000.0, "后勤");

    }

 

    public Employee(int empno, String ename, double sal, String dept) {

       this.empno = empno;

       this.ename = ename;

       this.sal = sal;

       this.dept = dept;

    }

 

    public String getInfo() {

       return "雇员信息:" + "\n"

+ "\t|- 雇员 编号:" + this.empno + "\n"

              + "\t|- 雇员 姓名:" + this.ename + "\n"

+ "\t|- 雇员 工资:" + this.sal+ "\n"

+ "\t|- 雇员 部门:" + this.dept;

    }

}

 

public class StringDemo {

    public static void main(String args[]) {

       System.out.println(new Employee(7369, "Smith", 800.0, "财务部").getInfo());

    }

}

雇员信息:

    |- 雇员 编号:7369

    |- 雇员 姓名:Smith

    |- 雇员 工资:800.0

    |- 雇员 部门:财务部

本题目的目的是为了巩固构造方法间的互调用操作。

2.3 对象数组(重点)

数组是一组相关变量的集合,而对象数组,就是一组相关对象的集合,对象数组的定义方式与数组的格式一样,也分为两种:

格式一:动态初始化

● 声明并开辟数组空间:

类名称 对象数组名称[ ]  =  new 类名称[长度];

类名称 [ ] 对象数组名称  =  new 类名称[长度];

● 分步完成:

声明对象数组:

类名称 [ ] 对象数组名称 = null;

为数组开辟空间:

对象数组名称 = new 类名称 [长度];

如果使用的是动态初始化对象数组的形式,则开辟空间之后,数组中的每一个元素的内容都是null。

格式二:静态初始化

类名称 [ ] 对象数组名称 = { 实例化对象1,实例化对象2…} ;

类名称 [ ] 对象数组名称 = new 类名称 { 实例化对象1,实例化对象2…} ;

静态初始化之后,里面的内容就不会是null。

范例:动态初始化

package course_2;

 

class Person {

    private String name;

    private int age;

 

    public Person(String name, int age) {

       this.name = name;

       this.age = age;

    }

 

    public String getInfo() {

       return "Name:" + this.name + ",Age:" + this.age;

    }

}

 

public class StringDemo {

    public static void main(String args[]) {

       Person per[] = new Person[3];   // 开辟3个空间

        System.out.println(per);

       for (int i = 0; i < per.length; i++) {

           System.out.println(per[i]);

       }

       per[0] = new Person("Mary", 25);

       per[1] = new Person("Henry", 28);

       per[2] = new Person("Jones", 27);

       for (int i = 0; i < per.length; i++) {

           System.out.println(per[i].getInfo());

       }

    }

}

[LfirstCourse.Person;@3148aa23

null

null

null

Name:Mary,Age:25

Name:Henry,Age:28

Name:Jones,Age:27

使用动态初始化之后,数组中的每一个元素都必须分别进行对象的实例化操作。

注意:比较上面两个输出,如果只执行分步定义的第一步后,在输出语句后面加“.getInfo()”,则编译不了而出错;如果已经执行了分步定义的两个步骤(声明并开辟空间),在输出后面去掉“.getInfo()”,则输出结果是一堆内存地址。

范例:静态初始化

package course_2;

 

class Person {

    private String name;

    private int age;

 

    public Person(String name, int age) {

        this.name = name;

        this.age = age;

    }

 

    public String getInfo() {

        return "姓名:" + this.name + ",年龄:" + this.age;

    }

}

 

public class StringDemo {

    public static void main(String args[]) {

        Person per[] = new Person[] { new Person("张三", 20),

                new Person("李四", 25), new Person("王五", 30) }; // 开辟3个空间

        for (int i = 0; i < per.length; i++) {

            System.out.println(per[i].getInfo());

        }

    }

}

姓名:张三,年龄:20

姓名:李四,年龄:25

姓名:王五,年龄:30

实际对于对象数组的概念一直都在使用,例如:之前的字符串数组(String[])就是一个对象数组,对象数组的表示含义就是表示多个的意思。为了更好理解对象数组的概念,可以参考下面一张以上程序的内存分析图:

 

下面再通过一个程序完成一个对象数组的应用传递,例如:编写一个方法,可以进行对象数组的反转。

package course_2;

 

class Person {

    private String name;

    private int age;

 

    public Person(String name, int age) {

        this.name = name;

        this.age = age;

    }

 

    public String getInfo() {

        return "姓名:" + this.name + ",年龄:" + this.age;

    }

}

 

public class StringDemo {

    public static void main(String args[]) {

        Person per[] = new Person[] { new Person("张三", 20),

                new Person("李四", 25), new Person("王五", 30) }; // 开辟3个空间

        reverse(per);   // 进行字符串反转

        for (int i = 0; i < per.length; i++) {

            System.out.println(per[i].getInfo());

        }

    }

 

    public static void reverse(Person temp[]) { // 接收的是对象数组

        int centern = temp.length / 2; // 取得中间点

        int head = 0;

        int tail = temp.length - 1;

        for (int i = 0; i < centern; i++) {

            Person p = temp[head];

            temp[head] = temp[tail];

            temp[tail] = p;

            head++;

            tail--;

        }

    }

}

姓名:王五,年龄:30

姓名:李四,年龄:25

姓名:张三,年龄:20

此时程序的内存关系图如下:

 

引用操作的核心就在于地址上的变化,不管如何操作,永远都是一块堆内存被多个栈内存所指向。

package course_2;

 

class Person {

    private String name;

    private int age;

 

    public Person(String name, int age) {

        this.name = name;

        this.age = age;

    }

 

    public String getInfo() {

        return "姓名:" + this.name + ",年龄:" + this.age;

    }

}

 

public class StringDemo {

    public static void main(String args[]) {

        Person per1[] = new Person[] { new Person("张三", 20),

                new Person("李四", 25), new Person("王五", 30) }; // 开辟3个空间

        Person per2[] = new Person[] { new Person("赵六", 35),

                new Person("孙七", 40), new Person("王八", 45) };

        Person per3[] = new Person[per1.length + per2.length];

        System.arraycopy(per1, 0, per3, 0, per1.length);

        System.arraycopy(per2, 0, per3, per1.length, per2.length);

        for (int i = 0; i < per3.length; i++) {

            System.out.println(per3[i].getInfo());

        }

    }

}

姓名:张三,年龄:20

姓名:李四,年龄:25

姓名:王五,年龄:30

姓名:赵六,年龄:35

姓名:孙七,年龄:40

姓名:王八,年龄:45

通过代码的分析,可以发现数组的拷贝操作依然可以使用,即:不管是基本数据类型,还是引用数据类型的数组都是一样执行的,但是对于排序操作(java.util.Arrays.sort(per3))就不能使用了!

2.4 对象的比较操作(重点)

要判断一个类的两个对象是否相等,肯定要比较两个对象中的所以属性的内容是否相等,最简单的实现方式如下:

package course_2;

 

class Person {

    private String name;

    private int age;

 

    public Person(String name, int age) {

       this.name = name;

       this.age = age;

    }

 

    public String getName() {

       return this.name;

    }

 

    public int getAge() {

       return this.age;

    }

}

 

public class StringDemo {

    public static void main(String args[]) {

       Person per1 = new Person("张三", 20);

       Person per2 = new Person("张三", 20);

       if (per1.getName().equals(per2.getName())

              && per1.getAge() == per2.getAge()) {

           System.out.println("两个对象相等!");

       } else {

           System.out.println("两个对象不相等!");

       }

    }

}

两个对象相等!

判断两个对象是否相等,实际上是自己的一种功能,但是以上的程序呢?

主方法或者说是主类,实际上在开发中来讲属于客户方(第三方),所谓的客户方指的就是调用程序的一方,所以对于客户端的操作应该越简单越好,那么以上的操作之中是将一些具体功能交给客户端实现了,很明显这样客户端太复杂了,所以现在的代码应该修改。

package course_2;

 

class Person {

    private String name;

    private int age;

 

    public Person(String name, int age) {

        this.name = name;

        this.age = age;

    }

 

    // 当一个类的对象传递到类的内部之后最大的好处在于:可以直接通过对象调用私有操作

    public boolean compare(Person per) { // 与指定的对象相比

        if (per == null) {

            return false;

        }

        if (per == this) { // 当前对象和传递进来的对象地址相同

            return true; // 地址相同,肯定是同一个对象

        }

        if (this.name.equals(per.name) && this.age == per.age) {

        //这个判断必须保证在实例化对象时设置上属性值(保证this.name非空),否则会出现NullPointerException异常。

            return true;

        }

        return false;

    }

 

    public String getName() {

        return this.name;

    }

 

    public int getAge() {

        return this.age;

    }

}

 

public class StringDemo {

    public static void main(String args[]) {

        Person per1 = new Person("张三", 20);

        Person per2 = new Person("张三", 20);

        if (per1pare(per2)) {

            System.out.println("两个对象相等!");

        } else {

            System.out.println("两个对象不相等!");

        }

    }

}

两个对象相等!

对象比较的关键有两点:

● 对象比较的操作一定是每一个类自己的功能;

● 一个类可以接收本类的引用,而且接收之后,可以直接通过这个对象调用类中的属性,不再需要使用getter方法,因为此时属于类的内容,内容是可以直接访问私有属性的。

2.5 引用的真实生活应用(重点)

程序来源于生活,只要通过合理的抽象,现实社会的一切都可以通过面向对象的关系分析出来,那么下面做个分析。

范例:要求现在表示出一种概念—— 每个人有一辆车

本程序如果换到了数据表的设计上肯定是一对一的操作关系,那么如果现在不是进行程序的开发,而是进行数据表的创建,则数据库创建脚本如下:

DROP TABLE car PURGE;

DROP TABLE member PURGE;

CREATE TABLE member (

       mid         NUMBER             PRIMARY KEY,

       name       VARCHAR2(20)    NOT NULL

);

CREATE TABLE car(

       mid         NUMBER             PRFERENCES member (mid),

       name      VARCHAR2(50)  NOT NULL

);

笔记:一对一的关系,应该还要把car表的mid列添加唯一约束吧。

这样的两张表依靠主键进行关联的操作,那么如果现在要进行类的设计呢?则肯定也要准备出两个类。

package course_2;

 

class Member {

    private int mid;

    private String name;

    private Car car; // 一人有一辆车

 

    public Member(int mid, String name) {

       this.mid = mid;

       this.name = name;

    }

 

    public String getMemberInfo() {

       return "编号:" + mid + ",姓名:" + name;

    }

 

    public void setCar(Car car) {

       this.car = car;

    }

 

    public Car getCar() {

       return this.car;

    }

}

 

class Car {

    private String name;

    private Member menber;

 

    public Car(String name) {

       this.name = name;

    }

 

    public String getCarInfo() {

       return "车的名称:" + name;

    }

 

    public void setMember(Member member) {

       this.menber = member;

    }

 

    public Member getMember() {

       return this.menber;

    }

}

 

public class StringDemo {

    public static void main(String args[]) {

       Member mem = new Member(1, "张三");

       Car car = new Car("BMW");

       mem.setCar(car); // 一人有一辆车

       car.setMember(mem); // 一辆车属于一个人

       System.out.println(mem.getMemberInfo());

       System.out.println(mem.getCar().getCarInfo());

    }

}

编号:1,姓名:张三

车的名称:BMW

此时就是依靠了程序表示出一对一的操作关系,而且对于以下的代码:

mem.getCar().getCarInfo()

这种程序在开发中称为“代码链”,中间依靠“. ”进行链接。

在这里就可以无限地循环点:car.getMember().getCar().getMember()…..

如果说现在进一步呢,例如:每一个还有一个孩子,孩子还可能有汽车。

package course_2;

 

class Member {

    private int mid;

    private String name;

    private Car car; // 一人有一辆车

    private Member child; // 一人有一个孩子

 

    public Member(int mid, String name) {

       this.mid = mid;

       this.name = name;

    }

 

    public String getMemberInfo() {

       return "编号:" + mid + ",姓名:" + name;

    }

 

    public void setChild(Member child) {

       this.child = child;

    }

 

    public Member getChild() {

       return this.child;

    }

 

    public void setCar(Car car) {

       this.car = car;

    }

 

    public Car getCar() {

       return this.car;

    }

}

 

class Car {

    private String name;

    private Member menber;

 

    public Car(String name) {

       this.name = name;

    }

 

    public String getCarInfo() {

       return "车的名称:" + name;

    }

 

    public void setMember(Member member) {

       this.menber = member;

    }

 

    public Member getMember() {

       return this.menber;

    }

}

 

public class StringDemo {

    public static void main(String args[]) {

       Member mem = new Member(1, "张三");

       Member chi = new Member(2, "张子");

       Car car = new Car("BMW");

       Car c = new Car("碰碰车");

       mem.setCar(car); // 一人有一辆车

       car.setMember(mem); // 一辆车属于一个人

       mem.setChild(chi); // 一个人有一个孩子

       chi.setCar(c); // 孩子有一辆车

       c.setMember(chi); // 一辆车属于一个孩子

       System.out.println(mem.getMemberInfo());

       System.out.println(mem.getCar().getCarInfo());

       System.out.println(mem.getChild().getMemberInfo());

       System.out.println(mem.getChild().getCar().getCarInfo());

    }

}

编号:1,姓名:张三

车的名称:BMW

编号:2,姓名:张子

车的名称:碰碰车

实际上这种人和孩子的关系有点类似于:emp和mgr的关系。

2.6 思考题(核心)

可以使用之前的emp类继续完成开发,而且为了节约时间,可以暂时不写setter、getter

要求表示出scott.emp和scott.dept之间的操作关系,并且编写数据测试,使用的字段:

● scott.emp :empno、ename、job、sal、comm、deptno、mgr;

● scott.dept :deptno、dname、loc;

本程序肯定还是两个类完成,这两个类的关系:

● 雇员和领导:一对一的自身关联;

● 部门雇员:一对多的关联,既然要想表现出多的概念,那么肯定要使用对象数组完成;

DIY:

package course_2;

 

class Emp {

    private int empno;

    private String ename;

    private String job;

    private double sal;

    private double comm;

    private Dept dept;

 

    public Emp() {

    }

 

    public Emp(int empno, String ename, String job, double sal, double comm) {

        this.setCom(comm);

        this.setEmpno(empno);

        this.setEname(ename);

        this.setJob(job);

        this.setSal(sal);

    }

 

    public String getEmpInfo() {

        return "雇员信息: " + "\n" + "\t|- 编号: " + this.getEmpno() + "\n"

                                    + "\t|- 姓名: " + this.getEname() + "\n"

                                       + "\t|- 职位: "+ this.getJob() + "\n"

                                       + "\t|- 工资: " + this.getSal() + "\n"

                                     + "\t|- 奖金: " + this.getComm() + "\n"

                                       + "\t|- 月薪: "+ this.salary() + "\n"

                                       + "\t|- 年薪: " + this.income();

    }

 

    public double salary() {

        return sal + comm;

    }

 

    public double income() {

        return this.salary() * 12;

    }

 

    public void setEname(String n) {

        ename = n;

    }

 

    public void setEmpno(int n) {

        empno = n;

    }

 

    public void setJob(String j) {

        job = j;

    }

 

    public void setSal(double s) {

        sal = s;

    }

 

    public void setCom(double c) {

        comm = c;

    }

 

    public void setDept(Dept dept) {

        this.dept = dept;

    }

 

    public Dept getDept() {

        return this.dept;

    }

 

    public int getEmpno() {

        return empno;

    }

 

    public String getEname() {

        return ename;

    }

 

    public String getJob() {

        return job;

    }

 

    public double getSal() {

        return sal;

    }

 

    public double getComm() {

        return comm;

    }

 

}

 

class Dept {

    private String dept;

    private int deptno;

    private String loc;

    private Emp emp;

 

    public Dept(String dept, int deptno, String loc) {

        this.dept = dept;

        this.deptno = deptno;

        this.loc = loc;

    }

 

    public void setEmp(Emp emp) {

        this.emp = emp;

    }

 

    public String getDeptInfo() {

        return "部门信息:" + "\n"

+ "\t|- 部门编号: " + this.deptno + "\n"

                + "\t|- 部门名:" + this.dept + "\n"

+ "\t|- 位置:" + this.loc;

    }

}

 

public class Demo {

    public static void main(String args[]) {

        Emp emp = new Emp(7369, "SMISH", "CHERK", 800, 10);

        Dept dept = new Dept("销售部", 14, "北京");

        emp.setDept(dept);

        dept.setEmp(emp);

        System.out.println(emp.getEmpInfo());

        System.out.println(emp.getDept().getDeptInfo());

    }

}

雇员信息:

    |- 编号: 7369

    |- 姓名: SMISH

    |- 职位: CHERK

    |- 工资: 800.0

    |- 奖金: 10.0

    |- 月薪: 810.0

    |- 年薪: 9720.0

部门信息:

    |- 部门编号: 14

    |- 部门名:销售部

    |- 位置:北京

Answer:

package course_2;

 

class Emp {

    private int empno;

    private String ename;

    private String job;

    private double sal;

    private double comm;

    private Emp mgr; // 每个雇员有一个领导

    private Dept dept; // 每个雇员属于一个部门

 

    public Emp() {

    }

 

    public Emp(int empno, String ename, String job, double sal, double comm) {

        thism = comm;

        this.empno = empno;

        this.ename = ename;

        this.job = job;

        this.sal = sal;

    }

 

    public String getEmpInfo() {

        return "雇员信息: " + "\n" +

                "\t|- 编号: " + this.empno + "\n" +

                "\t|- 姓名: "+ this.ename + "\n" +

                "\t|- 职位: " + this.job + "\n"+

                "\t|- 工资: " + this.sal + "\n" +

                "\t|- 奖金: " + thism;

    }

 

    public void setMgr(Emp mgr) {

        this.mgr = mgr;

    }

 

    public Emp getMgr() {

        return this.mgr;

    }

 

    public void setDept(Dept dept) {

        this.dept = dept;

    }

 

    public Dept getDept() {

        return this.dept;

    }

 

}

 

class Dept {

    private String dname;

    private int deptno;

    private String loc;

    private Emp[] emps; // 每个部门有多个雇员

 

    public Dept(int deptno, String dname, String loc) {

        this.dname = dname;

        this.deptno = deptno;

        this.loc = loc;

    }

 

    public void setEmps(Emp[] emps) {

        this.emps = emps;

    }

 

    public Emp[] getEmps() {

        return this.emps;

    }

 

    public String getDeptInfo() {

        return "部门信息:" + "\n" +

                "\t|- 部门编号: " + this.deptno + "\n"+

                "\t|- 部门名:" + this.dname + "\n" +

                "\t|- 位置:" + this.loc;

    }

 

}

 

public class Demo {

    public static void main(String args[]) {

        Emp allEmp[] = new Emp[] { new Emp(7369, "SMISH", "CHERK", 800.0, 10),

                new Emp(7566, "ALLEN", "MANAGER", 2450.0, 100),

                new Emp(7839, "KING", "PRESIDENT", 5000.0, 0) };

 

        Dept dept = new Dept(10, "ACCOUNT", "New York");

        // 先设置雇员和领导的关系

        allEmp[0].setMgr(allEmp[1]);

        allEmp[1].setMgr(allEmp[2]);

        // 设置雇员和部门的关系,每个雇员都有部门

        allEmp[0].setDept(dept);

        allEmp[1].setDept(dept);

        allEmp[2].setDept(dept);

        // 一个部门有多个雇员

        dept.setEmps(allEmp);

        // 信息的输出:

        System.out.println(dept.getDeptInfo());

        System.out.println("部门人数:" + dept.getEmps().length);

        for (int x = 0; x < dept.getEmps().length; x++) {

            Emp emp = dept.getEmps()[x];     //注意这个用法

            System.out.println(emp.getEmpInfo());

            // 也可以用下面这条语句输出:

            // System.out.println(allEmp[x].getEmpInfo());

            if (emp.getMgr() != null) { // 存在领导

                System.out.println("他的领导:\n" + emp.getMgr().getEmpInfo());

            } else {

                System.out.println("他没领导!");

            }

            System.out.println("-----------------------------");

        }

    }

}

部门信息:

    |- 部门编号: 10

    |- 部门名:ACCOUNT

    |- 位置:New York

部门人数:3

雇员信息:

    |- 编号: 7369

    |- 姓名: SMISH

    |- 职位: CHERK

    |- 工资: 800.0

    |- 奖金: 10.0

他的领导:

雇员信息:

    |- 编号: 7566

    |- 姓名: ALLEN

    |- 职位: MANAGER

    |- 工资: 2450.0

    |- 奖金: 100.0

-----------------------------

雇员信息:

    |- 编号: 7566

    |- 姓名: ALLEN

    |- 职位: MANAGER

    |- 工资: 2450.0

    |- 奖金: 100.0

他的领导:

雇员信息:

    |- 编号: 7839

    |- 姓名: KING

    |- 职位: PRESIDENT

    |- 工资: 5000.0

    |- 奖金: 0.0

-----------------------------

雇员信息:

    |- 编号: 7839

    |- 姓名: KING

    |- 职位: PRESIDENT

    |- 工资: 5000.0

    |- 奖金: 0.0

他没领导!

-----------------------------

对于这样的程序肯定是必须能够分析出来的,而且这种程序是作为日后开发的核心基础所在,不可忽视,通过这样的程序思路,以后可以表示出:

● 一个停车场有多辆汽车,每辆汽车都有一个司机;

● 一个学校有多间教室,每个教室有多套桌椅和多个学生,每个学生有自己使用的桌椅和电脑;

● 一个房间有多扇窗户,一个门,若干个灯所组成;

简单java类表示出的是某一类的信息,但是不同的类之间会存在关系,这种就可以通过引用数据类型来进行表示,如果对于此类思路不明确的,好好完成以上的题目,以后这个思路肯定是重点使用的。

现在通过如上的代码也可以发现一个问题:简单java类和数据表;

● 表名称 = 类名称;

● 表字段 = 类中的属性;

● 表中的每行记录 = 类的每一个对象;

所以简单java类的设计原则就等同与表的原则,就是要进行事务的抽象分析。

2.7 数据结构——简单链表(理解)

对象数组:可以保存一组对象,但是对象数组有一个天生的问题就是其数组的长度是固定的,而在开发之中为了不受对象数组长度的限制,所以引入链表这种数据结构。

所谓的链表程序实际上就是使用节点包装所需要保存的数据。

如果要想完成链表的开发,则首先应该定义出节点的操作类,以保存String型数据为例,可以定义一个Node类;

class Node {

    private String data; // 要包装的数据

    private Node next; // 保存它的下一个节点

 

    public Node(String data) { // Node类的功能一定要包装数据

       this.data = data;

    }

 

    public void setNext(Node next) {

       this.next = next;

    }

 

    public Node getNext() {

       return this.next;

    }

 

    public String getData() {

       return this.data;

    }

}

范例:手工配置节点的关系并输出

public class Demo {

    public static void main(String args[]) {

       Node root = new Node("根节点");

       Node n1 = new Node("保存数据A");

       Node n2 = new Node("保存数据B");

       Node n3 = new Node("保存数据C");

        Node n4 = new Node("保存数据D");

       Node n5 = new Node("保存数据E");

       // 下面应该配置这些节点之间的操作关系

       root.setNext(n1);

       n1.setNext(n2);

       n2.setNext(n3);

       n3.setNext(n4);

       n4.setNext(n5);

       // 假设有多个节点,不知道循环多少次要使用while循环

       // 循环的结束条件应该是一个节点如果没有下一个节点

       // 如果要输出肯定从根节点开始输出

       Node currNode = root; // 找到根节点

       while (currNode != null) { // 有节点

           System.out.println("数据:" + currNode.getData());

           currNode = currNode.getNext(); // 更改当前节点为其下一个节点

       }

    }

}

数据:根节点

数据:保存数据A

数据:保存数据B

数据:保存数据C

数据:保存数据D

数据:保存数据E

但是以上的输出操作并不是合理的做法,更合理的做法应该使用递归完成输出。

    public static void main(String args[]) {

       Node root = new Node("根节点");

       Node n1 = new Node("保存数据A");

       Node n2 = new Node("保存数据B");

       Node n3 = new Node("保存数据C");

       Node n4 = new Node("保存数据D");

       Node n5 = new Node("保存数据E");

       // 下面应该配置这些节点之间的操作关系

       root.setNext(n1);

       n1.setNext(n2);

       n2.setNext(n3);

       n3.setNext(n4);

       n4.setNext(n5);

       printNode(root);

    }

 

    public static void printNode(Node node) {

       if (node != null) {

           System.out.println(node.getData());

           printNode(node.getNext()); // 找到下一个

       }

    }

根节点

保存数据A

保存数据B

保存数据C

保存数据D

保存数据E

以上完成了一个最简单的链表操作,应该可以理解链表中的数据保存形式,可是以上的代码是通过用户手工配置完成的,很明显不可取,用户所关心的肯定只是数据的保存,而对于这些节点的安排用户根本就不需要关心,所以为了可以让程序自动的安排节点,就需要编写一个结点的操作类—— link。

不过是自动完成操作,还是手工完成操作,链表的核心就在于根节点上,肯定第一个保存的数据要作为根节点;

分析过程:

1、第一个保存进来的节点肯定是作为根节点存在,因为所有的操作都要通过根节点展开;

2、第二个节点必须判断根节点是否存在,如果存在则肯定要保存在根节点之后(next),但是这个过程应该由Node类自己进行处理;

3、第三个节点进来之后,肯定要保存在“某一个已经保存的最后一个节点之后,而判断保存位置的最后做法就是,判断某一个当前节点是否是null”。

  

现在已经实现了数据的增加和输出的功能,那么如何查询一个数据是否存在呢?

● 还应该是从根节点开始查找,而且查找的过程应该交给Node类完成

既然可以进行节点的增加,那么该如何进行节点的删除呢?

对于节点的删除操作要考虑两种情况:

● 情况一:根节点是要删除的节点,把根节点设置为根节点的下一个;

情况二:删除的不是根节点而是其他节点,例如,假设要删除的是第二个节点;

package course_2;

 

class Node {

    private String data; // 要包装的数据

    private Node next; // 保存它的下一个节点

 

    public Node(String data) { // Node类的功能一定要包装数据

       this.data = data;

    }

 

    public void setNext(Node next) {

       this.next = next;

    }

 

    public Node getNext() {

       return this.next;

    }

 

    public String getData() {

       return this.data;

    }

 

    public void addNode(Node newNode) { // 将节点保存在合适的位置上

       if (this.next == null) { // 当前节点后没有其他节点

           this.next = newNode; // 保存

       } else { // 当前节点之后有内容

           this.next.addNode(newNode); // 当前节点的下一个节点保存

       }

    }

 

    public void printNode() {

       System.out.println(this.data); // 输出当前节点的数据

       if (this.next != null) { // 还有后面的节点

           this.next.printNode();

        }

    }

 

    public boolean containsNode(String data) {

       if (this.data.equals(data)) { // 当前节点的数据为查找数据

           return true;

       } else { // 当前节点的数据不是查找数据,继续向下

           if (this.next != null) { // 现在没有查找到最后的节点

              return this.next.containsNode(data);

           } else { // 后面没有节点

               return false;

           }

       }

    }

 

    public void removeNode(Node previous, String data) {

       if (this.data.equals(data)) { // 当前 节点的数据满足删除

           previous.next = this.next; // 空出当前节点

       } else {

           this.next.removeNode(this, data); // 向下继续删除

       }

    }

}

 

class Link { // 表示链表的操作类,主要就是操作Node类

    private Node root; // 将根节点定义为类中的属性

 

    public void add(String data) { // 设置要增加的数据

       if (data == null) { // 如果没有数据

           return; // 返回到被调用处

       }

       Node newNode = new Node(data); // 将数据包装在节点

       if (this.root == null) { // 现在没有根节点

           this.root = newNode; // 第一个节点作为根节点

       } else { // 如果不是根节点,则通过Node类指定保存的位置

           this.root.addNode(newNode);

       }

    }

 

    public void print() {

       if (this.root != null) { // 现在 有节点有数据,可以保存

           this.root.printNode(); // 输出还是交给Node

       }

    }

 

    public boolean contains(String data) {

       if (data == null || this.root == null) {

           return false; // 没有内容就不查

       }

       return this.root.containsNode(data);// 交给Node类完成

    }

 

    public void remove(String data) {

       if (this.contains(data)) { // 要删除存在的节点

           if (this.root.getData().equals(data)) { // 如果删除的是根节点

              this.root = this.root.getNext(); // 根节点的下一个节点为根

           } else { // 交给Node类完成

              // 从根节点的下一个节点开始,判断要删除的节点

              this.root.getNext().removeNode(this.root, data);

           }

       }

    }

}

 

public class Demo {

    public static void main(String args[]) {

       Link all = new Link();

       all.add("A");

       all.add("B");

       all.add("C");

       all.remove("B");

       all.remove("A");

       all.print();

       System.out.println(all.contains("A"));

       System.out.println(all.contains("X"));

    }

 

}

C

false

false

此时就是完成了一个最简单的链表,在本程序之中,一定要明确的发现各个操作之间的关系,明白Link和Node类之间的操作联系,链表的核心就在于根节点的操作上。

对于链表本程序至少一个简单的单向链表的部分工具,而实际上对于链表还可能有:

● 单向循环链表:最后一个节点指向不是null而是根节点;

● 双向链表:现在的程序只保留下一个节点,而双向链表会保留它的上一个节点;

● 双向循环链表:双方都进行了链接。

本程序实话来讲是一个以后包括面试和一些java类的实现原理,在面试之中经常也会出现类似的题目。

2.8 二叉树(了解)

二叉树(Binary Tree)也是一种比较常见的数据结构,二叉树的存放原则如下:

● 取出第一个数据保存在根节点之中;

● 比根节点数据小的要放在左子树;

● 比根节点数据大的要放在右子树;

而且对于二叉树排序而言,最后还应该按照中序遍历的操作进行输出:左 → 根 → 右;

所以现在要想实现二叉树的关键是必须有一个可以判断大小的操作,如果是普通数字可以直接使用关系运算判断,但是如果保存的是字符串呢?使用compareTo( )方法完成,下面演示一个保存和输出。

不管如何操作,有一点是绝对不会变的,所有的数据结构之中,Node类是必须存在的,因为Node类的功能有两个,一个是包装数据,另外一个是保存下一个节点的引用;

package course_2;

 

class Node {

    private String data; // 要包装的数据

    private Node left; // 保存左子树

    private Node right; // 保存右子树

 

    public Node(String data) { // Node类的功能一定要包装数据

       this.data = data;

    }

 

    public void setLeft(Node left) {

       this.left = left;

    }

 

    public void setRight(Node right) {

       this.right = right;

    }

 

    public String getData() {

       return this.data;

    }

 

    public Node getLeft() {

       return this.left;

    }

 

    public Node getRight() {

       return this.right;

    }

 

    public void addNode(Node newNode) { // 增加节点

       if (newNode.getData()pareTo(this.data) < 0) { // 小于

           if (this.left == null) { // left节点没有内容

              this.left = newNode; // 保存在左子树

           } else {

              this.left.addNode(newNode); // 向下继续保存

           }

       } else {

           if (this.right == null) {

              this.right = newNode;

           } else {

              this.right.addNode(newNode); // 保存在右子树

           }

       }

    }

 

    public void printNode() {

       if (this.left != null) { // 有左子树

           this.left.printNode();

       }

       System.out.println(this.data);

       if (this.right != null) {

           this.right.printNode();

       }

    }

}

 

class BinaryTree { // 二叉树

    private Node root; // 根节点

 

    public void add(String data) {

       Node newNode = new Node(data); // 数据都要封装为节点

       if (this.root == null) { // 根节点为空

           this.root = newNode; // 第一个节点作为根节点

       } else { // 应该交给Node类保存在合适的位置上

           this.root.addNode(newNode); // 给Node类处理

       }

    }

 

    public void print() {

       if (this.root != null) {

           this.root.printNode();

       }

    }

}

 

public class Demo {

    public static void main(String args[]) {

       BinaryTree bt = new BinaryTree();

       bt.add("B");

       bt.add("C");

       bt.add("A");

       bt.print();

    }

}

A

B

C

二叉树除了可以保存数据之外,最大的用处是进行排序,但是不管是何种操作,都是根节点的操作,都是Node的保存形式不同而已。

3、总结

1、新知识:this关键字、对象数组;

1)       this关键字:

● this属性:表示操作的是当前类中的属性,而且也强调了,只有是类中的属性前面都要加上“this.” ;

● this.方法( ):表示的是类中的操作方法;

● this( ):表示调用类中的构造方法,但是在使用此语句调用的时候一定要留有出口,必须放在构造方法的首行;

● this表示当前对象:当前正在操作类方法的对象,成为当前对象:

2)    对象数组:是包含了多个对象,但是对象数组本身会受到数组长度的限制;

● 对象数组的动态初始化:类名称对象数组名称[ ] = new 类名称 [长度],开辟之后每个内容都是null;

● 对象数组的静态初始化:类名称对象数组名称 [ ] = new 类名称 [ ] {对象1,对象2,…};

● 在使用对象数组的时候,可以进行数组的拷贝,但是排序暂时无法使用;

3)    对象比较:对象比较是一个类本身所具备的一种功能,属于类本身的方法,而且对象的比较需要将每一个属性都进行依次的判断;

2、简单java类的关系指定及与现实生活以及数据表之间的对应关系;

● 类名称 = 表名称;

● 类属性 = 表字段;

● 类对象 = 表的每行记录,对象数组 = 表的多行记录;

● 而且表之间的主外键链接,可以使用引用关系进行表示;

3、对于链表的操作一定要明白其原理,可以自己独立的编写增加和输出两个操作;

4、作业

1、完成如下一个程序:

有一个Person类(name、age属性),要求可以在链表中保存多个Person对象,可以实现增加、输出全部、查询、删除数据;

提示:可以直接参考已经给出的操作程序完成。

本程序的关键有两点:

● 在Node类中所保存的应该是Person对象数组;

● 在Person类中应该提供compare( )方法进行对象的比较;

DIY

package course_2;

 

class Person {

    private String name;

    private int age;

    private Person next;

 

    public Person(String name, int age) {

        this.name = name;

        this.age = age;

    }

 

    public String getName() {

        return name;

    }

 

    public void setNext(Person next) {

        this.next = next;

    }

 

    public Person getNext() {

        return this.next;

    }

 

    public void addNode(Person newNode) {

        if (this.next == null) {

            this.next = newNode;

        } else {

            this.next.addNode(newNode);

        }

    }

 

    public void printNode() {

        System.out.println(this.name + "  " + this.age);

        if (this.next != null) {

            this.next.printNode();

        }

    }

 

    public boolean containsNode(String name) {

        if (this.name.equals(name)) {

            return true;

        } else {

            if (this.next != null) {

                return this.next.containsNode(name);

            } else {

                return false;

            }

        }

    }

 

    public void removeNode(Person previous, String name) {

        if (this.name.equals(name)) {

            previous.next = this.next;

        } else {

            this.next.removeNode(this, name);

        }

    }

}

 

class Link {

    private Person root;

 

    public void add(String name, int age) {

        Person newNode = new Person(name, age);

        if (root == null) {

            this.root = newNode;

        } else {

            this.root.addNode(newNode);

        }

    }

 

    public void print() {

        if (root != null) {

            root.printNode();

        }

    }

 

    public boolean contains(String name) {

        if (name == null || this.root == null) {

            return false;

        }

        return root.containsNode(name);

    }

 

    public void remove(String name) {

        if (this.contains(name)) {

            if (this.root.getName().equals(name)) {

                this.root = this.root.getNext();

            } else {

                this.root.getNext().removeNode(this.root, name);

            }

        }

    }

}

 

public class Demo {

    public static void main(String args[]) {

        Link li = new Link();

        li.add("Alex", 15);

        li.add("Mary", 22);

        li.add("Smith", 37);

        System.out.println(li.contains("Alex"));

        li.remove("Mary");

        li.print();

    }

}

true

Alex  15

Smith  37

Answer

package course_2;

 

class Person {

    private String name;

    private int age;

 

    // 按照简单java类的要求,应该提供无参,但是本程序为了简便不再写暂时不用的程序

    public Person(String name, int age) {

       this.name = name;

       this.age = age;

    }

 

    public void setName(String name) {

       this.name = name;

    }

 

    public void setAge(int age) {

       this.age = age;

    }

 

    public String getName() {

       return this.name;

    }

 

    public int getAge() {

       return this.age;

    }

 

    public boolean compare(Person per) {

       if (per == null) { // 传入的per对象是null

           return false; // 直接表示不是同一个对象

       }

       if (per == this) { // 比较的是两个对象的地址

           return true; // 地址相同肯定是同一个对象

       }

       // 类的对象传回本类之中可以直接通过“对象.属性”操作

       if (this.name.equals(per.name) && this.age == per.age) { // 所有属性都依次判断

           return true; // 对象内容相等

       } else {

           return false; // 对象内容不相等

       }

    }

 

    public String getPersonInfo() { // 所有的操作返回后输出

       return "姓名:" + this.name + ",年龄:" + this.age;

    }

}

 

class Node { // 表示节点,为了封装数据,并且可以指向下一个节点

    private Person data; // 现在要保存的数据是Person类型

    private Node next; // 保存下一个节点

 

    public Node(Person data) { // 要进行封装的数据

       this.data = data;

    }

 

    public void setNext(Node next) {

       this.next = next;

    }

 

    public Node getNext() {

       return this.next;

    }

 

    public Person getData() {

       return this.data;

    }

 

    public void addNode(Node newNode) {

       if (this.next == null) {

           this.next = newNode; // 保存新的节点

       } else {

           this.next.addNode(newNode); // 向下继续保存

       }

    }

 

    public void printNode() {

       System.out.println(this.data.getPersonInfo());// 输出当前节点的数据

       if (this.next != null) {

           this.next.printNode(); // 向下继续输出节点

       }

    }

 

    public boolean containsNode(Person data) {

       if (this.datapare(data)) { // 当前节点为要查询的节点

           return true;

       } else {

           if (this.next != null) {

              return this.next.containsNode(data);// 向下继续查询

           } else {

              return false; // 没有此记录

           }

       }

    }

 

    public void removeNode(Node previous, Person data) {

       if (this.datapare(data)) { // 当前节点为要删除的节点

           previous.next = this.next; // 空出当前节点

       } else {

           this.next.removeNode(this, data);

       }

    }

}

 

class Link { // 主要的功能是操作链表

    private Node root; // 操作的核心在于根节点上

 

    public String print() {

       if (this.root != null) { // 现在已经存在了根节点

           this.root.printNode();// 输出全部的节点

       }

       return "no parameter!";

    }

 

    public void add(Person data) { // 增加新的节点数据

       if (data == null) { // 增加的数据为空就不增加了

           return;

       }

       Node newNode = new Node(data);// 将数据封装到节点之中

       if (this.root == null) { // 现在不存在根节点

           this.root = newNode; // 将新的节点作为根节点出现

       } else { // 根节点已经存在,交给节点类自己排序

           this.root.addNode(newNode);

       }

    }

 

    public boolean contains(Person data) { // 查询数据

       if (this.root == null || data == null) {

           return false;

       }

       return this.root.containsNode(data);

    }

 

    public void remove(Person data) {

       if (this.contains(data)) { // 要删除的节点存在

           if (this.root.getData()pare(data)) { // 根节点为要删除的节点

              this.root = this.root.getNext();

           } else {

              this.root.getNext().removeNode(this.root, data);

           }

       }

    }

}

 

public class Demo {

    public static void main(String args[]) {

       Link all = new Link();

       all.add(new Person("张三", 20));

       all.add(new Person("李四", 22));

       all.add(new Person("王五", 25));

       all.remove(new Person("李四", 22));

       all.print();

       System.out.println(all.contains(new Person("王五", 25)));

       System.out.println(all.contains(new Person("王五", 35)));

 

    }

}

姓名:张三,年龄:20

姓名:王五,年龄:25

true

false

本程序虽然完成了,但是也同时可以发现存在以下四个问题:

● 问题一:Node类现在不应该被外部所看见,因为除了Link类之外,Node类基本不关心;

● 问题二:Node类和Link类现在并非是一样的,因为这之间还要使用getter操作;

● 问题三:如果现在节点类中保存的是其他数据,则整个代码都要换;

● 问题四:输出的时候依然需要使用每一个类所独有的方法完成;

本代码只是对链表的概念做了一个基本的铺垫,并没有真正的可以应用在实际的开发之中。

2、熟悉2.5节 ~ 2.6节的代码,多写几遍,并且自己设计一些场景编写;

5、测试题

1、定义一个数组,要求其内容为其下标,并且实现数组的反转功能;

DIY

    public static void main(String args[]) {

       int data[] = new int[7];

       for (int i = 0; i < data.length; i++) {

           data[i] = i;

       }

       for (int i = 0; i < data.length / 2; i++) {

           int temp = data[i];

           data[i] = data[data.length - i - 1];

           data[data.length - i - 1] = temp;

       }

       for (int i = 0; i < data.length; i++) {

           System.out.print(data[i] + "  ");

       }

    }

6  5  4  3  2  1  0 

Answer

    public static void main(String args[]) {

       int data[] = new int[10];

       init(data);

       reverse(data);

       print(data);

    }

 

    public static void init(int arr[]) {

       for (int i = 0; i < arr.length; i++) {

           arr[i] = i;

       }

    }

 

    public static void print(int arr[]) {

       for (int i = 0; i < arr.length; i++) {

           System.out.print(arr[i] + " ");

       }

    }

 

    public static void reverse(int arr[]) {

       int center = arr.length / 2; // 求出数组的中间点

       int head = 0; // 从头开始据算下标

       int tail = arr.length - 1; // 从尾开始计算下标

       for (int i = 0; i < center; i++) {

           int temp = arr[head];

           arr[head] = arr[tail];

           arr[tail] = temp;

       }

    }

9 1 2 3 4 5 6 7 8 0

 

2、统计出每种工资等级的人数,平均工资、以及此等级的最高和最低工资;

Answer

SELECT s.grade,s.losal,s.hisal,COUNT(e.empno),AVG(sal)

FROM emp e,salgrade s

WHERE e.sal between s.losal and s.hisal

GROUP BY s.grade,s.losal,s.hisal;

 

3、查处所有高于30部门平均工资的雇员姓名、职位、工资、部门名称;

Answer

SELECT e.ename,e.job,e.sal,d.dname

FROM emp e,dept d

WHERE e.deptno=d.deptno AND e.sal>(

       SELECT AVG(sal)

       FROM emp WHERE deptno=30);

 

4、写出Strng类的主要特点(必须熟记);

|- 有两种实例化方式;

1.        直接字符串赋值:在堆内存之中只开辟一块空间,可以自动入池,以备下次继续使用;

2.        通过构造方法完成:会产生两块堆内存空间,不会自动入池,可以使用intern()方法手工入池;

|- 字符串比较:

1.    “= =”:比较的是两个字符串所在的堆内存地址的比较,属于数值比较;

2.   “equals”:是String类中提供的一个方法,进行内容的比较;

|- 一个字符串常量就是String的匿名对象,是会占堆内存的;

|- 字符串的内容一旦声明之后则不可改变,改变的只是内存地址的指向;

 

5、写出String类的操作方法(不少于15个)

   写清楚方法的返回值类型,参数名称及个数、方法名称。

|- 字符数组和字符串转换:

Ø  【构造】public String(char c[ ]);

Ø  【构造】public String(char c[ ],intoffset,int len);

Ø  【普通】public char[] toCharArray();

Ø  【普通】public char charAt();

|- 字节数组和字符串转换:

Ø  【构造】public String(byte b[ ]);

Ø  【构造】public String(byte b,intoffset,int len);

Ø  【普通】public byte[ ] getBytes();

Ø  【构造】public byte[ ] getBytes(Stringcharset);

|- 字符串拆分:

Ø  【普通】public String[ ] split(Stringregex);

Ø  【普通】public String[ ] split(Strngregex,int size);

|- 字符串比较:

Ø  【普通】public boolean equals(Stringother);

Ø  【普通】public booleaneuqalsIgnoreCase(String other);

Ø  【普通】public int compareTo(Stingstr);   →  >0、<0、=0

|- 字符串检索:

Ø  【普通】public boolean contains(Stringstr);

Ø  【普通】public int indexOf(String str);

Ø  【普通】public int indexOf(Stringstr,int offset);

Ø  【普通】public int lastIndexOf(Stringstr,);

Ø  【普通】public int lastIndexOf(Stringstr,int offset);

Ø  【普通】public boolean startsWith(Stringstr);

Ø  【普通】public boolean endsWith(Stringstr);

|- 字符串截取:

Ø  【普通】public String substring(intbegin);

Ø  【普通】public String substring(intbegin,int end);

|- 字符串替换:

Ø  【普通】public Sting replaceAll(StingoldStr,Sting newStr);

Ø  【普通】public String replaceFirst(StringoleStr,String newStr)

|- 其他方法

Ø  【普通】public int length();

Ø  【普通】public String trim();

Ø  【普通】public boolean isEmpty();

Ø  【普通】public String toLowerCase(Stringstr);

Ø  【普通】public String toUpperCase(Stringstr);


更多推荐

Java SE 3rd day:Object

本文发布于:2024-03-09 07:45:37,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1724349.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:SE   Java   Object   day

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!