Java_02 快速入门 面向对象

目录

第一章:面向对象基础知识

1.2  类与对象

范例1-1:定义类。

范例1-2:使用类——在主类中使用Book类。

范例1-3:以分步的方式实例化对象。

范例1-4:使用未实例化的对象。

范例1-5:声明两个对象。

范例1-6:对象引用传递。

范例1-7:深入观察引用传递。

1.3  封装性初步分析

范例1-8:观察没有封装的代码。

范例1-9:使用private封装属性。

范例1-10:为Book类中的封装属性设置setter、getter操作。

1.4  构造方法

范例1-11:定义构造方法。

范例1-12:利用构造方法为属性赋值。

范例1-13:构造方法重载。

1.5  匿名对象

范例1-14:定义匿名对象。

1.6  简单Java类

范例1-15:开发Emp程序类。

范例1-16:编写测试程序。

1.7  数组

范例1-17:定义数组。

范例1-18:分步实现数组操作。

范例1-19:数组的引用传递。

范例1-20:数组的静态初始化。

范例1-21:观察二维数组的定义及使用。

范例1-22:一个数组传递的程序。

范例1-23:简化理解。

范例1-24:实现一个数组排序。

范例1-25:实现数组的转置(首位交换)。

范例1-26:方法返回数组。

范例1-27:实现数组复制。

范例1-28:实现排序。

范例1-29:对象数组的动态初始化。

范例1-30:对象数组的静态初始化。

1.8  String类的基本概念

范例1-31:为String类对象直接赋值。

范例1-32:利用构造方法实例化。

范例1-33:判断两个int型整数是否相等。

范例1-34:在String对象上使用“==”比较。

范例1-35:实现字符串内容比较。

范例1-36:观察字符串是匿名对象的验证。

范例1-37:观察问题。

范例1-38:回避NullPointerException问题。

范例1-39:观察直接赋值时的堆内存自动引用。

范例1-40:不自动保存对象池操作。

范例1-41:手工入池。

范例1-42:修改字符串对象引用。

范例1-43:观察以下代码问题。

1.9  String类的常用方法

范例1-44:取出指定索引的字符——使用charAt()方法。

范例1-45:字符数组与字符串的转换。

范例1-46:将字符串转为大写。

范例1-47:给定一个字符串,要求判断其是否由数字组成。

范例1-48:观察字符串与字节数组的转换。

范例1-49:相等判断。

范例1-50:观察compareTo()方法。

范例1-51:使用indexOf()等功能查找。

范例1-52:利用indexOf()方法判断子字符串是否存在。

范例1-53:使用contains()方法判断子字符串是否存在。

范例1-54:开头或结尾判断。

范例1-55:观察替换的结果。

范例1-56:验证操作。

范例1-57:进行全部拆分。

范例1-58:字符串全部拆分。

范例1-59:拆分为指定的个数。

范例1-60:错误的拆分操作。

范例1-61:正常的拆分操作。

范例1-62:复杂拆分。

范例1-63:字符串连接。

范例1-64:转小写与转大写操作。

范例1-65:去掉左右空格。

范例1-66:取消掉全部空格。

范例1-67:取得字符串长度。

范例1-68:判断是否为空字符串。

范例1-69:实现首字母大写的操作。

1.10  this关键字

范例1-70:观察程序问题。

范例1-71:使用this关键字明确地表示访问类中的属性。

范例1-72:调用本类普通方法。

范例1-73:观察程序问题。

范例1-74:消除掉构造方法中的重复代码。

范例1-75:观察错误的代码。

范例1-76:直接输出对象。

1.11  引用传递

范例1-77:第一道引用传递范例。

范例1-78:第二道引用范例。

范例1-79:实现int数据的接收。

范例1-80:第三道引用传递。

范例1-81:数据库创建脚本。

范例1-82:代码实现(无参构造、setter、getter略,同时本程序定义的是两个简单Java类)。

范例1-83:代码测试。

范例1-84:修改Member类定义。

范例1-85:描述电脑组成关系。

1.12  数据表与简单Java类映射

范例1-86:代码实现。

范例1-87:设置并取得数据。

1.13  对象比较

范例1-88:基础的比较方式。

范例1-89:观察封装属性的进一步操作。

范例1-90:对象比较实现。

范例1-91:定义程序。

范例1-92:在没有实例化对象产生时直接操作static属性。

范例1-93:使用static定义方法。

范例1-94:观察如下代码。

范例1-95:不使用static声明方法。

范例1-96:定义一个数学的加法操作。

范例1-97:得到参数。

1.15  代码块

范例1-98:编写普通代码块。

范例1-99:说明代码。

范例1-100:定义构造块。

范例1-101:利用静态块为static属性初始化。

范例1-102:JDK 1.7之前的Bug。

1.16  内部类

范例1-103:观察内部类的基本形式。

范例1-104:将内部类放到外部并且实现同样功能。

范例1-105:访问内部类的私有属性。

范例1-106:使用this访问外部类属性。

范例1-107:实例化内部类对象。

范例1-108:定义私有内部类

范例1-109:利用static定义内部类。

范例1-110:实例化“外部类”对象。

范例1-111:在普通方法里面定义内部类。

范例1-112:访问方法中定义的参数或变量。

范例1-113:JDK 1.7之前的代码。

1.17  链表

范例1-114:定义一个Node类。

范例1-115:手工配置节点关系,并使用while循环输出全部节点数据。

范例1-116:手工配置节点关系,通过递归输出全部节点数据。

范例1-117:链表的基本形式。

范例1-118:链表的基本开发结构。

范例1-119:修改Link.java类。

范例1-120:判断是否为空链表。

范例1-121:在Node类增加方法。

范例1-122:修改Link。

范例1-123:定义测试程序。

范例1-124:在Link类里面增加一个foot的属性,表示每一个Node元素的编号。

范例1-125:在每一次查询时(一个链表可能查询多次),foot应该都从头开始计算(foot设为0)。

范例1-126:在Node类里面实现getNode()方法,内部类和外部类之间可以方便地进行私有属性的互相访问。

范例1-127:在Node类里面增加setNode()方法。

范例1-128:在Link类里面增加set()方法。

范例1-128:在Node类里面增加一个removeNode()方法,此方法专门负责处理非根节点的删除。

范例1-129:在Link类里面增加根节点的判断。

范例1-130:修改Link类的定义。

范例1-131:在Node类里面处理数组数据的保存。

范例1-132:清空链表。

范例1-133:定义一个保存图书信息的类。

范例1-134:修改链表实现(本代码主要是将之前的链表类中的String类型更换为Book类型,对象比较更换为compare()方法)。

范例1-135:实现测试。


章:面向对象基础知识

1.2  类与对象

范例1-1:定义类。

class Book { // 定义一个新的类

    String title; // 书的名字

    double price; // 书的价格

    /**

     * 输出对象完整信息

     */

    public void getInfo() { // 此方法将由对象调用

        System.out.println("图书名称:" + title + ",价格:" + price);

    }

}

范例1-2:使用类—在主类中使用Book类。

class Book { // 定义一个新的类

    String title; // 书的名字

    double price; // 书的价格

    public void getInfo() { // 此方法将由对象调用

        System.out.println("图书名称:" + title + ",价格:" + price);

    }

}

public class TestDemo {

    public static void main(String args[]) {

        Book bk = new Book() ; // 声明并实例化对象

        bk.title = "Java开发" ;   // 操作属性内容

        bk.price = 89.9 ; // 操作属性内容

        bk.getInfo() ; // 调用类中的getInfo()方法

    }

}

范例1-3:以分步的方式实例化对象。

public class TestDemo {

    public static void main(String args[]) {

        Book bk = null; // 声明对象

        bk = new Book(); // 实例化对象开辟了堆内存

        bk.title = "Java开发"; // 操作属性内容

        bk.price = 89.9; // 操作属性内容

        bk.getInfo(); // 调用类中的getInfo()方法

    }

}

范例1-4:使用未实例化的对象。

public class TestDemo {

    public static void main(String args[]) {

        Book bk = null; // 声明对象

        bk.title = "Java开发"; // 操作属性内容

        bk.price = 89.9; // 操作属性内容

        bk.getInfo(); // 调用类中的getInfo()方法

    }

}

范例1-5:声明两个对象。

public class TestDemo {

    public static void main(String args[]) {

        Book bookA = new Book() ; // 声明并实例化第一个对象

        Book bookB = new Book() ; // 声明并实例化第个对象

        bookA.title = "Java开发" ; // 设置第一个对象的属性内容

        bookA.price = 89.8 ; // 设置第一个对象的属性内容

        bookB.title = "JSP开发" ; // 设置第二个对象的属性内容

        bookB.price = 69.8 ; // 设置第二个对象的属性内容

        bookA.getInfo() ; // 调用类中的方法输出信息

        bookB.getInfo() ; // 调用类中的方法输出信息

    }

}

范例1-6:对象引用传递。

public class TestDemo {

    public static void main(String args[]) {

        Book bookA = new Book() ; // 声明并实例化第一个对象

        Book bookB = null ; // 声明第二个对象

        bookA.title = "Java开发" ; // 设置第一个对象的属性内容

        bookA.price = 89.8 ; // 设置第一个对象的属性内容

        bookB = bookA ;   // 引用传递

        bookB.price = 69.8 ; // 利用第二个对象设置属性内容

        bookA.getInfo() ; // 调用类中的方法输出信息

    }

}

范例1-7:深入观察引用传递。

public class TestDemo {

    public static void main(String args[]) {

        Book bookA = new Book() ; // 声明并实例化第一个对象

        Book bookB = new Book() ; // 声明并实例化第二个对象

        bookA.title = "Java开发" ; // 设置第一个对象的属性内容

        bookA.price = 89.8 ; // 设置第一个对象的属性内容

        bookB.title = "JSP开发" ; // 设置第二个对象的属性内容

        bookB.price = 69.8 ; // 设置第二个对象的属性内容

        bookB = bookA ;   // 引用传递

        bookB.price = 100.1 ; // 利用第二个对象设置属性内容

        bookA.getInfo() ; // 调用类中的方法输出信息

    }

}

1.3  封装性初步分析

范例1-8:观察没有封装的代码。

class Book { // 定义一个新的类

    String title; // 书的名字

    double price; // 书的价格

    public void getInfo() { // 此方法将由对象调用

        System.out.println("图书名称:" + title + ",价格:" + price);

    }

}

public class TestDemo {

    public static void main(String args[]) {

        Book book = new Book(); // 声明并实例化对象

        book.title = "Java开发"; // 设置属性内容

        book.price = -89.9; // 设置属性内容

        book.getInfo(); // 调用方法

    }

}

范例1-9:使用private封装属性。

class Book { // 定义一个新的类

    private String title; // 书的名字

    private double price; // 书的价格

    public void getInfo() { // 此方法将由对象调用

        System.out.println("图书名称:" + title + ",价格:" + price);

    }

}

public class TestDemo {

    public static void main(String args[]) {

        Book book = new Book(); // 声明并实例化对象

        book.title = "Java开发"; // 设置属性内容

        book.price = -89.9; // 设置属性内容

        book.getInfo(); // 调用方法

    }

}

范例1-10:为Book类中的封装属性设置setter、getter操作。

class Book { // 定义一个新的类

    private String title; // 书的名字

    private double price; // 书的价格

    /**

     * 设置或修改title属性内容

     * @param t 接收要设置的数据

     */

    public void setTitle(String t) { // 设置title属性内容

        title = t;

    }

    /**

     * 设置或修改price属性内容

     * @param p 接收要设置的数据

     */

    public void setPrice(double p) { // 设置price属性内容

        if (p > 0.0) { // 进行数据验证

           price = p ;

        }

    }

    /**

     * 取得title属性内容

     * @return title属性数据

     */

    public String getTitle() { // 取得title属性内容

        return title;

    }

    /**

     * 取得price属性内容

     * @return price属性数据

     */

    public double getPrice() { // 取得price属性内容

        return price;

    }

    /**

     * 输出对象完整信息

     */

    public void getInfo() { // 此方法将由对象调用

        System.out.println("图书名称:" + title + ",价格:" + price);

    }

}

public class TestDemo {

    public static void main(String args[]) {

        Book book = new Book(); // 声明并实例化对象

        book.setTitle("Java开发"); // 设置属性内容

        book.setPrice(-89.9); // 设置属性内容

        book.getInfo(); // 调用方法

    }

}

1.4  构造方法

范例1-11:定义构造方法。

class Book { // 定义一个新的类

    /**

     * Book无参构造方法

     */

    public Book() { // 构造方法

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

    }

}

public class TestDemo {

    public static void main(String args[]) {

        Book book = null ; // 声明对象不调用构造

        book = new Book() ; // 实例化对象调用构造

    }

}

范例1-12:利用构造方法为属性赋值。

class Book { // 定义一个新的类

    private String title; // 书的名字

    private double price; // 书的价格

    /**

     * Book类构造方法用于设置titleprice属性的内容

     * @param t title属性内容

     * @param p price属性内容

     */

    public Book(String t,double p) { // 定义构造方法

        setTitle(t) ; // 调用本类方法

        setPrice(p) ; // 调用本类方法

    }

    public void setTitle(String t) { // 设置title属性内容

        title = t;

    }

    public void setPrice(double p) { // 设置price属性内容

        price = p ;

    }

    public String getTitle() { // 取得title属性内容

        return title;

    }

    public double getPrice() { // 取得price属性内容

        return price;

    }

    public void getInfo() { // 此方法将由对象调用

        System.out.println("图书名称:" + title + ",价格:" + price);

    }

}

public class TestDemo {

    public static void main(String args[]) {

        Book book = new Book("Java开发", 69.8); // 声明并实例化对象

        book.getInfo(); // 调用方法

    }

}

范例1-13:构造方法重载。

class Book { // 定义一个新的类

    private String title; // 书的名字

    private double price; // 书的价格

    /**

     * Book类无参构造方法

     */

    public Book() { // 无参的无返回值的构造方法

        System.out.println("无参构造") ;

    }

    /**

     * Book类构造方法用于设置title属性的内容

     * @param t title属性内容

     */

    public Book(String t) { // 有一个参数的构造

        title = t ; // 直接为属性赋值

        System.out.println("有一个参数的构造") ;

    }

    /**

     * Book类构造方法用于设置titleprice属性的内容

     * @param t title属性内容

     * @param p price属性内容

     */

    public Book(String t,double p) { // 有两个参数的构造

        title = t ; // 直接为属性赋值

        price = p ; // 直接为属性赋值

        System.out.println("有两个参数的构造") ;

    }

    // settergetter

    public void getInfo() { // 此方法将由对象调用

        System.out.println("图书名称:" + title + ",价格:" + price);

    }

}

public class TestDemo {

    public static void main(String args[]) {

        Book book = new Book("Java开发"); // 声明并实例化对象

        book.getInfo(); // 调用方法

    }

}

1.5  匿名对象

范例1-14:定义匿名对象。

class Book { // 定义一个新的类

    private String title; // 书的名字

    private double price; // 书的价格

    public Book(String t,double p) { // 有两个参数的构造

        title = t ; // 直接为属性赋值

        price = p ; // 直接为属性赋值

    }

    // settergetter

    public void getInfo() { // 此方法将由对象调用

        System.out.println("图书名称:" + title + ",价格:" + price);

    }

}

public class TestDemo {

    public static void main(String args[]) {

        new Book("Java开发", 69.8).getInfo(); // 匿名对象

    }

}

1.6  简单Java类

范例1-15:开发Emp程序类。

class Emp { // 定义一个雇员类

    private int empno; // 雇员编号

    private String ename; // 雇员姓名

    private String job; // 雇员职位

    private double sal; // 基本工资

    private double comm; // 佣金

    public Emp() { // 明确定义一个无参构造方法

    }

    public Emp(int eno, String ena, String j, double s, double c) { // 有参构造

        empno = eno; // 为属性赋值

        ename = ena; // 为属性赋值

        job = j; // 为属性赋值

        sal = s; // 为属性赋值

        comm = c; // 为属性赋值

    }

    public void setEmpno(int e) { // 设置empno属性内容

        empno = e;

    }

    public void setEname(String e) { // 设置ename属性内容

        ename = e;

    }

    public void setJob(String j) { // 设置job属性内容

        job = j;

    }

    public void setSal(double s) { // 设置sal属性内容

        sal = s;

    }

    public void setComm(double c) { // 设置comm属性内容

        comm = c;

    }

    public int getEmpno() { // 取得empno属性内容

        return empno;

    }

    public String getEname() { // 取得ename属性内容

        return ename;

    }

    public String getJob() { // 取得job属性内容

        return job;

    }

    public double getSal() { // 取得sal属性内容

        return sal;

    }

    public double getComm() { // 取得comm属性内容

        return comm;

    }

    /**

     * 取得简单Java类的基本信息信息在被调用处输出

     * @return 包含对象完整信息的字符串数据

     */

    public String getInfo() { // 取得完整信息

        Return "雇员编号:" + empno + "\n" +

               "雇员姓名:" + ename + "\n" +

               "雇员职位:" + job + "\n" +

               "基本工资:" + sal + "\n" +

               "    :" + comm ;

    }

}

范例1-16:编写测试程序。

public class TestDemo {

    public static void main(String args[]) {

        Emp e = new Emp(7369, "SMITH", "CLERK", 800.0, 1.0); // 实例化对象

        System.out.println(e.getInfo()); // 取得对象信息

    }

}

1.7  数组

范例1-17:定义数组。

public class ArrayDemo {

    public static void main(String args[]) {

        int data[] = new int[3]; // 声明并开辟了一个3个长度的数组

        data[0] = 10; // 设置数组内容

        data[1] = 20; // 设置数组内容

        data[2] = 30; // 设置数组内容

        for (int x = 0; x < data.length; x++) { // 循环输出数组

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

        }

    }

}

范例1-18:分步实现数组操作。

public class ArrayDemo {

    public static void main(String args[]) {

        int data [] = null ; // 声明数组

        data = new int [3] ; // 开辟数组空间

        data[0] = 10; // 设置数组内容

        data[1] = 20; // 设置数组内容

        data[2] = 30; // 设置数组内容

        for (int x = 0; x < data.length; x++) { // 循环输出数组

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

        }

    }

}

范例1-19:数组的引用传递。

public class ArrayDemo {

    public static void main(String args[]) {

        int data[] = new int[3]; // 声明并开辟了一个3个长度的数组

        data[0] = 10; // 设置数组内容

        data[1] = 20; // 设置数组内容

        data[2] = 30; // 设置数组内容

        int temp[] = data; // 数组引用传递

        temp[0] = 99; // 修改数组内容

        for (int x = 0; x < data.length; x++) { // 循环输出数组

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

        }

    }

}

范例1-20:数组的静态初始化。

public class ArrayDemo {

    public static void main(String args[]) {

        int data[] = new int[] { 1, 2, 3, 4, 5 }; // 数组的静态初始化

        for (int x = 0; x < data.length; x++) { // 循环输出数组

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

        }

    }

}

范例1-21:观察二维数组的定义及使用。

public class ArrayDemo {

    public static void main(String args[]) {

        int data [][] = new int [][] {

           {1,2,3} ,{4,5,6} , {7,8,9}

        } ; // 定义二维数组

        for (int x = 0; x < data.length; x++) { // 外层循环是控制数组的数据行内容

           for (int y = 0; y < data[x].length; y++) { // 内层循环是控制数组的数据列内容

               System.out.print(data[x][y] + "\t");

           }

           System.out.println(); // 换行

        }

    }

}

范例1-22:一个数组传递的程序。

public class ArrayDemo {

    public static void main(String args[]) {

        int data[] = new int[] { 1, 2, 3 }; // 开辟数组

        change(data); // 引用传递等价于:int temp [] = data ;

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

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

        }

    }

    /**

     * 此方法的主要功能是进行数组数据的改变操作,在本方法中会将数组中的每个元素内容乘2

     * @param temp 要进行改变内容的数组引用

     */

    public static void change(int temp[]) { // 此方法定义在主类中,并且由主方法直接调用

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

            temp[x] *= 2; // 将数组的内容乘2保存

        }

    }

}

范例1-23:简化理解。

public class ArrayDemo {

    public static void main(String args[]) {

        int data[] = new int[] { 1, 2, 3 }; // 开辟数组

        int temp [] = data ; // 引用传递

        for (int x = 0 ; x < temp.length ; x ++) { // 修改数组内容

            temp[x] *= 2 ; // 将数组的内容乘2保存

        }

        for (int x = 0; x < data.length; x++) { // 循环输出数据

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

        }

    }

}

范例1-24:实现一个数组排序。

数组的排序操作在笔试中经常被问到,下面给出(升序)排序的基本原理。

—  原始数据: 2、1、9、0、5、3、7、6、8;

—  第一次排序: 1、2、0、5、3、7、6、8、9;

—  第二次排序: 1、0、2、3、5、6、7、8、9;

—  第三次排序: 0、1、2、3、5、6、7、8、9。

以上只是给出了排序的基础原理过程,根据数据的不同会出现不同的排序次数,但是不管有多少个数据,总的排序次数不会超过数组的长度。所以只要排序的次数达到“长度*长度”,那么所有的数据一定可以排序成功。

(1)排序基础实现

public class ArrayDemo {

    public static void main(String args[]) {

        int data[] = new int[] { 2, 1, 9, 0, 5, 3, 7, 6, 8 };

        System.out.print("排序前的数据:");

        print(data); // 排序前输出数据

        for (int x = 0; x < data.length; x++) { // 外层控制排序总体的次数

            for (int y = 0; y < data.length - 1; y++) { // 内层控制每次的排序控制

               if (data[y] > data[y + 1]) { // 判断是否需要交换

                  int t = data[y];

                  data[y] = data[y + 1];

                  data[y + 1] = t;

               }

            }

        }

        System.out.print("排序后的数据:");

        print(data); // 排序后的输出数据

    }

    /**

     * 此方法的主要功能是进行数组数据输出操作在输出完成后会追加一个换行

     * @param temp 要进行改变内容的数组引用

     */

    public static void print(int temp[]) { // 专门定义一个输出的功能的方法

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

            System.out.print(temp[x] + "");

        }

        System.out.println();

    }

}

(2)改善设计

在代码编写中主方法是作为程序的起点存在的,所有的程序起点都可以称为客户端。既然是客户端,所有的代码编写一定要简单,因此可以采用方法进行封装。

public class ArrayDemo {

    public static void main(String args[]) {

        int data [] = new int [] {2,1,9,0,5,3,7,6,8} ;

        sort(data) ; // 实现排序

        print(data) ;

    }

    /**

     * 数组排序操作将接收到的数组对象内容进行升序排列

     * @param arr 数组对象的引用

     */

    public static void sort(int arr[]) { // 这个方法专门负责排序

        for (int x = 0 ; x < arr.length ; x ++) { // 外层控制排序总体的次数

           for (int y = 0 ; y < arr.length - 1 ; y ++) { // 内层控制每次的排序控制

               if (arr[y] > arr[y + 1]) { // 判断需要交换

                 int t = arr[y] ;

                 arr[y] = arr[y + 1] ;

                 arr[y + 1] = t ;

               }

           }

        }

    }

    public static void print(int temp[]) { // 专门定义一个输出的功能的方法

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

            System.out.print(temp[x] + "") ;

        }

        System.out.println() ;

        }

}

范例1-25:实现数组的转置(首位交换)。

下面首先来解释一下转置的概念(一维数组实现)。

原始数组: 1、2、3、4、5、6、7、8;

转置后的数组: 8、7、6、5、4、3、2、1。

如果要想实现转置的操作,有以下两个思路。

—  解决思路一:首定义一个新的数组,然后将原始数组按照倒序的方式插入到新的数组中,最后改变原始数组引用,将其指向新的数组空间。

public class ArrayDemo {

    public static void main(String args[]) {

        int data [] = new int [] {1,2,3,4,5,6,7,8} ;

        int temp [] = new int [data.length] ; // 首先定义一个新的数组长度与原始数组一致

        int foot = data.length - 1; // 控制data数组的索引

        for (int x = 0 ; x < temp.length ; x ++) { // 对于新的数组按照索引由小到大的顺序循环

            temp[x] = data[foot] ;

            foot -- ;

        } // 此时temp的内容就是转置后的结果

        data = temp ; // data指向temp,data的原始数据就称为垃圾

        print(data) ; // 输出数组

    }

    public static void print(int temp[]) { // 专门定义一个输出功能的方法

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

            System.out.print(temp[x] + "") ;

        }

        System.out.println() ;

    }

}

范例1-26:方法返回数组。

public class ArrayDemo {

    public static void main(String args[]) {

        int data[] = init() ; // 接收数组

        print(data) ;

        System.out.println("数组长度:" + init().length) ; // 返回的数组可直接使用length取得长度

    }

    /**

     * 数组初始化的操作方法,此方法可以返回一个数组的引用

     * @return 包含3个元素的数组对象

     */

    public static int[] init() { // 方法返回数组

        return new int [] {1,2,3} ; // 直接返回匿名数组

    }

    public static void print(int temp[]) { // 数组输出

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

            System.out.print(temp[x] + "") ;

        }

        System.out.println() ;

    }

}

范例1-27:实现数组复制。

—  数组A:1、2、3、4、5、6、7、8;

—  数组B:11、22、33、44、55、66、77、88;

—  将数组A的部分内容替换到数组B中,数组B的最终结果为:11、22、5、6、7、66、77、88。

public class ArrayDemo {

    public static void main(String args[]) {

        int dataA[] = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 }; // 定义数组

        int dataB[] = new int[] { 11, 22, 33, 44, 55, 66, 77, 88 };// 定义数组

        System.arraycopy(dataA, 4, dataB, 2, 3); // 数组复制

        print(dataB);

    }

    public static void print(int temp[]) { // 打印数组内容

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

            System.out.print(temp[x] + "");

        }

        System.out.println();

    }

}

范例1-28:实现排序。

public class ArrayDemo {

    public static void main(String args[]) {

        int data[] = new int[] { 3, 6, 1, 2, 8, 0 };

        java.util.Arrays.sort(data); // 数组排序

        print(data);

    }

    public static void print(int temp[]) { // 数组输出

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

            System.out.print(temp[x] + "");

        }

        System.out.println();

    }

}

范例1-29:对象数组的动态初始化。

class Book {

    private String title ;

    private double price ;

    public Book(String t,double p) {

        title = t ;

        price = p ;

    }

    // settergetter、无参构造略

    public String getInfo() {

        return "书名:" + title + ",价格:" + price ;

    }

}

public class ArrayDemo {

    public static void main(String args[]) {

        Book books [] = new Book[3] ; // 开辟了一个3个长度的对象数组内容为null

        books[0] = new Book("Java",79.8) ; // 对象数组中的每个数据都需要分别实例化

        books[1] = new Book("JSP",69.8) ; // 对象数组中的每个数据都需要分别实例化

        books[2] = new Book("Android",89.8) ; // 对象数组中的每个数据都需要分别实例化

        for (int x = 0 ; x < books.length ; x ++) { // 循环对象数组

            System.out.println(books[x].getInfo()) ;

        }

    }

}

范例1-30:对象数组的静态初始化。

public class ArrayDemo {

    public static void main(String args[]) {

        Book books[] = new Book[] {

                new Book("Java", 79.8),

                new Book("JSP", 69.8),

                new Book("Android", 89.8) }; // 开辟了一个3个长度的对象数组

        for (int x = 0; x < books.length; x++) { // 循环输出对象数组内容 

            System.out.println(books[x].getInfo());

        }

    }

}

1.8  String类的基本概念

范例1-31:为String类对象直接赋值。

public class StringDemo {

    public static void main(String args[]) {

        String str = "www.YOOTK.com"; // 直接赋值

        System.out.println(str); // 输出字符串数据

    }

}

范例1-32:利用构造方法实例化。

public class StringDemo {

    public static void main(String args[]) {

        String str = new String("www.YOOTK.com"); // 直接赋值

        System.out.println(str); // 输出字符串数据

    }

}

范例1-33:判断两个int型整数是否相等。

public class StringDemo {

    public static void main(String args[]) {

        int x = 10; // 整型变量

        int y = 10; // 整型变量

        System.out.println(x == y); // 判断是否相等

    }

}

范例1-34:在String对象上使用“==”比较。

public class StringDemo {

    public static void main(String args[]) {

        String stra = "hello"; // 直接赋值定义字符串

        String strb = new String("hello"); // 构造方法定义字符串

        String strc = strb; // 引用传递

        System.out.println(stra == strb); // 比较结果:false

        System.out.println(stra == strc); // 比较结果:false

        System.out.println(strb == strc); // 比较结果:true

    }

}

范例1-35:实现字符串内容比较。

public class StringDemo {

    public static void main(String args[]) {

        String stra = "hello"; // 直接赋值定义字符串

        String strb = new String("hello"); // 构造方法定义字符串

        String strc = strb; // 引用传递

        System.out.println(stra.equals(strb)) ; // 比较结果:true

        System.out.println(stra.equals(strc)) ; // 比较结果:true

        System.out.println(strb.equals(strc)) ; // 比较结果:true

    }

}

范例1-36:观察字符串是匿名对象的验证。

public class StringDemo {

    public static void main(String args[]) {

        String str = "hello"; // str是对象名称"hello"是内容

        System.out.println("hello".equals(str)); // 内容比较由字符串直接调用

    }

}

范例1-37:观察问题。

public class StringDemo {

    public static void main(String args[]) {

        String input = null; // 假设这个内容由用户输入

        if (input.equals("hello")) { // 如果输入内容是hello,认为满足一个条件

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

        }

    }

}

范例1-38:回避NullPointerException问题。

public class StringDemo {

    public static void main(String args[]) {

        String input = null; // 假设这个内容由用户输入

        if ("hello".equals(input)) { // 如果输入内容是hello,认为满足一个条件

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

        }

    }

}

范例1-39:观察直接赋值时的堆内存自动引用。

public class StringDemo {

    public static void main(String args[]) {

        String stra = "hello"; // 直接赋值实例化

        String strb = "hello"; // 直接赋值实例化

        String strc = "hello"; // 直接赋值实例化

        String strd = "yootk" ; // 直接赋值实例化内容不相同

        System.out.println(stra == strb); // 判断结果:true

        System.out.println(stra == strc); // 判断结果:true

        System.out.println(strb == strc); // 判断结果:true

        System.out.println(stra == strd); // 判断结果:false

    }

}

范例1-40:不自动保存对象池操作。

public class StringDemo {

    public static void main(String args[]) {

        String stra = new String("hello"); // 使用构造方法定义了新的内存空间不会自动入池

        String strb = "hello"; // 直接赋值

        System.out.println(stra == strb); // 判断结果:false

    }

}

范例1-41:手工入池。

public class StringDemo {

    public static void main(String args[]) {

        String stra = new String("hello").intern(); // 使用构造方法定义新的内存空间手工入池

        String strb = "hello"; // 直接赋值

        System.out.println(stra == strb); // 判断结果:true

    }

}

范例1-42:修改字符串对象引用。

public class StringDemo {

    public static void main(String args[]) {

        String str = "Hello "; // 直接赋值实例化String类对象

        str = str + "World "; // 字符串连接同时修改String类对象的引用关系

        str += "!!!"; // 字符串连接,同时修改String类对象的引用关系

        System.out.println(str); // 输出当前的String类对象内容

    }

}

范例1-43:观察以下代码问题。

public class StringDemo {

    public static void main(String args[]) {

        String str = ""; // 实例化字符串对象

        for (int x = 0; x < 1000; x++) { // 循环1000

            str += x; // 修改字符串对象引用

        }

        System.out.println(str);

    }

}

1.9  String类的常用方法

范例1-44:取出指定索引的字符—使用charAt()方法。

public class StringDemo {

    public static void main(String args[]) {

        String str = "hello"; // 定义字符串对象

        char c = str.charAt(0); // 截取第一个字符

        System.out.println(c); // 输出字符

    }

}

范例1-45:字符数组与字符串的转换。

public class StringDemo {

    public static void main(String args[]) {

        String str = "hello"; // 定义字符串

        char[] data = str.toCharArray(); // 将字符串变为字符数组

        for (int x = 0; x < data.length; x++) { // 循环输出每一个字符

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

        }

    }

}

范例1-46:将字符串转为大写。

public class StringDemo {

    public static void main(String args[]) {

        String str = "hello"; // 字符串由小写字母组成

        char[] data = str.toCharArray(); // 将字符串变为字符数组

        for (int x = 0; x < data.length; x++) { // 改变每一个字符的编码值

            data[x] -= 32;

        }

        System.out.println(new String(data)); // 将全部字符数组变为String

        System.out.println(new String(data, 1, 2)); // 将部分字符数组变为String

    }

}

范例1-47:给定一个字符串,要求判断其是否由数字组成。

思路:如果整个字符串要判断是不是数字是无法实现的,但是可以将字符串变为字符数组,然后判断每一个字符的内容是否是数字,如果该字符的范围在('0'~'9')指定的范畴之内,那么就是数字。

public class StringDemo {

    public static void main(String args[]) {

        String str = "123423432";

        if (isNumber(str)) {

          System.out.println("字符串由数字组成!");

        } else {

          System.out.println("字符串由非数字组成!");

        }

    }

    /**

     * 判断字符串是否由数字所组成

     * @param temp 要判断的字符串数据

     * @return 如果字符串由数字组成返回true,否则返回false

     */

    public static boolean isNumber(String temp) {

        char[] data = temp.toCharArray(); // 将字符串变为字符数组可以取出每一位字符进行判断

        for (int x = 0; x < data.length; x++) { // 循环判断

            if (data[x] > '9' || data[x] < '0') { // 不是数字字符范围

              return false; // 后续不再判断

            }

        }

        return true; // 如果全部验证通过返回true

    }

}

范例1-48:观察字符串与字节数组的转换。

public class StringDemo {

    public static void main(String args[]) {

        String str = "helloworld"; // 定义字符串

        byte[] data = str.getBytes(); // 将字符串变为字节数组

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

            data[x] -= 32; // 将小写字母变为大写形式

        }

        System.out.println(new String(data)); // 全部转换

        System.out.println(new String(data, 5, 5)); // 部分转换

    }

}

范例1-49:相等判断。

public class StringDemo {

    public static void main(String args[]) {

        String stra = "Hello"; // 实例化字符串对象

        String strb = "hELLO"; // 实例化字符串对象

        System.out.println(stra.equals(strb)); // 比较结果:false

        System.out.println(stra.equalsIgnoreCase(strb)); // 比较结果:true

    }

}

范例1-50:观察compareTo()方法。

public class StringDemo {

    public static void main(String args[]) {

        String stra = "Hello"; // 定义字符串对象

        String strb = "HEllo"; // 定义字符串对象

        System.out.println(stra.compareTo(strb)); // 32,大于0

        if (stra.compareTo(strb) > 0) { // 可以利用大小等于0的方式来判断大小

           System.out.println("大于");

        }

    }

}

范例1-51:使用indexOf()等功能查找。

public class StringDemo {

    public static void main(String args[]) {

        String str = "helloworld"; // 实例化字符串对象

        System.out.println(str.indexOf("world")); // 返回满足条件单词的第一个字母的索引

        System.out.println(str.indexOf("l")); // 返回的是第一个查找到的子字符串位置

        System.out.println(str.indexOf("l", 5)); // 从第6个元素开始查找子字符串位置

        System.out.println(str.lastIndexOf("l")); // 从后向前开始查找指定字符串的位置

    }

}

范例1-52:利用indexOf()方法判断子字符串是否存在。

public class StringDemo {

    public static void main(String args[]) {

        String str = "helloworld"; // 字符串对象

        if (str.indexOf("world") != -1) { // 能找到子字符串

          System.out.println("可以查询到数据。");

        }

    }

}

范例1-53:使用contains()方法判断子字符串是否存在。

public class StringDemo {

    public static void main(String args[]) {

        String str = "helloworld"; // 字符串对象

        if (str.contains("world")) { // 子字符串存在

            System.out.println("可以查询到数据。");

        }

    }

}

范例1-54:开头或结尾判断。

public class StringDemo {

    public static void main(String args[]) {

        String str = "##@@hello**"; // 字符串对象

        System.out.println(str.startsWith("##")); // 是否以##开头

        System.out.println(str.startsWith("@@", 2)); // 从第2个索引开始是否以@@开头

        System.out.println(str.endsWith("**")); // 是否以**结尾

    }

}

范例1-55:观察替换的结果。

public class StringDemo {

    public static void main(String args[]) {

        String str = "helloworld" ; // 定义字符串

        String resultA = str.replaceAll("l","_") ; // 全部替换

        String resultB = str.replaceFirst("l","_") ; // 替换首个

        System.out.println(resultA) ;

        System.out.println(resultB) ;

    }

}

范例1-56:验证操作。

public class StringDemo {

    public static void main(String args[]) {

        String str = "helloworld"; // 定义字符串

        String resultA = str.substring(5); // 从指定索引截取到结尾

        String resultB = str.substring(0, 5); // 截取部分子字符串

        System.out.println(resultA);

        System.out.println(resultB);

    }

}

范例1-57:进行全部拆分。

public class StringDemo {

    public static void main(String args[]) {

        String str = "hello yootk nihao mldn"; // 定义字符串中间使用空格作为间隔

        String result[] = str.split(" "); // 字符串拆分

        for (int x = 0; x < result.length; x++) { // 循环输出

            System.out.print(result[x] + "");

        }

    }

}

范例1-58:字符串全部拆分。

public class StringDemo {

    public static void main(String args[]) {

        String str = "hello yootk"; // 定义字符串

        String result[] = str.split(""); // 字符串全拆分

        for (int x = 0; x < result.length; x++) { // 循环输出

            System.out.print(result[x] + "");

        }

    }

}

范例1-59:拆分为指定的个数。

public class StringDemo {

    public static void main(String args[]) {

        String str = "hello yootk nihao mldn"; // 定义字符串中间使用空格作为间隔

        String result[] = str.split(" ",2); // 字符串拆分

        for (int x = 0; x < result.length; x++) { // 循环输出

            System.out.println(result[x]);

        }

    }

}

范例1-60:错误的拆分操作。

public class StringDemo {

    public static void main(String args[]) {

        String str = "192.168.1.2"; // 定义字符串

        String result[] = str.split("."); // 字符串拆分

        for (int x = 0; x < result.length; x++) { // 循环输出

            System.out.print(result[x] + "");

        }

    }

}

范例1-61:正常的拆分操作。

public class StringDemo {

    public static void main(String args[]) {

        String str = "192.168.1.2"; // 定义字符串

        String result[] = str.split("\\."); // 字符串拆分

        for (int x = 0; x < result.length; x++) { // 循环输出

            System.out.print(result[x] + "");

        }

    }

}

范例1-62:复杂拆分。

public class StringDemo {

    public static void main(String args[]) {

        String str = "张三:20|李四:21|王五:22"; // 定义字符串

        String result[] = str.split("\\|"); // 第一次拆分

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

           String temp[] = result[x].split(":"); // 第二次拆分

           System.out.println("姓名:" + temp[0] + ",年龄:" + temp[1]);

        }

    }

}

范例1-63:字符串连接。

public class StringDemo {

    public static void main(String args[]) {

        String str = "hello".concat("world") ; // 等价于“+”

        System.out.println(str) ;

    }

}

范例1-64:转小写与转大写操作。

public class StringDemo {

    public static void main(String args[]) {

        String str = "(*(*Hello(*(*" ; // 定义字符串

        System.out.println(str.toUpperCase()) ; // 转大写后输出

        System.out.println(str.toLowerCase()) ; // 转小写后输出

    }

}

范例1-65:去掉左右空格。

public class StringDemo {

    public static void main(String args[]) {

        String str = "   hello   world  "; // 定义字符串包含空格

        System.out.println("" + str + ""); // 原始字符串

        System.out.println("" + str.trim() + ""); // 去掉空格后的字符串

    }

}

范例1-66:取消掉全部空格。

public class StringDemo {

    public static void main(String args[]) {

        String str = "   hello   world  "; // 定义字符串包含空格

        System.out.println(str.replaceAll(" ","")); // 去掉空格后的字符串

    }

}

范例1-67:取得字符串长度。

public class StringDemo {

    public static void main(String args[]) {

        String str = "helloworld"; // 定义字符串

        System.out.println(str.length()); // 取得字符串长度

    }

}

范例1-68:判断是否为空字符串。

public class StringDemo {

    public static void main(String args[]) {

        String str = "helloworld"; // 定义字符串

        System.out.println(str.isEmpty()); // 判断字符串对象的内容是否为空字符串不是null)

        System.out.println("".isEmpty());   // 判断字符串常量的内容是否为空字符串不是null)

    }

}

范例1-69:实现首字母大写的操作。

public class StringDemo {

    public static void main(String args[]) {

        String str = "yootk"; // 定义字符串

        System.out.println(initcap(str)); // 调用initcap()方法

    }

    /**

     * 实现首字母大写的操作

     * @param temp 要转换的字符串数据

     * @return 将首字母大写后返回

     */

    public static String initcap(String temp) {

        // 利用substring(0,1)取出字符串的第一位后将其变为大写再连接剩余的字符串

        return temp.substring(0, 1).toUpperCase() + temp.substring(1);

    }

}

1.10  this关键字

范例1-70:观察程序问题。

class Book {

    private String title;

    private double price;

    public Book(String title, double price) {

        title = title; // 原本的目的是希望将构造方法中的title变量内容设置给title属性

        price = price; // 原本的目的是希望将构造方法中的price变量内容设置给price属性

    }

    // settergetter

    public String getInfo() {

        return "书名:" + title + ",价格:" + price;

    }

}

public class TestDemo {

    public static void main(String args[]) {

        Book book = new Book("Java开发", 89.2);

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

    }

}

范例1-71:使用this关键字明确地表示访问类中的属性。

class Book {

    private String title;

    private double price;

    public Book(String title, double price) {

        this.title = title; // this.属性表示的是本类属性这样即使与方法中的参数重名也可以明确定位

        this.price = price; // this.属性表示的是本类属性这样即使与方法中的参数重名也可以明确定位

    }

    // settergetter

    public String getInfo() {

        return "书名:" + title + ",价格:" + price;

    }

}

public class TestDemo {

    public static void main(String args[]) {

        Book book = new Book("Java开发", 89.2);

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

    }

}

范例1-72:调用本类普通方法。

class Book {

    private String title;

    private double price;

    public Book(String title, double price) {

        this.title = title;

        this.price = price;

    }

    public void print() {

        System.out.println("更多课程请访问:www.yootk.com") ;

    }

    // settergetter

    public String getInfo() {

        this.print() ; // 调用本类方法

        return "书名:" + title + ",价格:" + price;

    }

}

public class TestDemo {

    public static void main(String args[]) {

        Book book = new Book("Java开发", 89.2);

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

    }

}

范例1-73:观察程序问题。

class Book {

    private String title;

    private double price;

    public Book() {

        System.out.println("一个新的Book类对象产生。"); // 把这行语句想象成50行代码

    }

    public Book(String title) {

        System.out.println("一个新的Book类对象产生。"); // 把这行语句想象成50行代码

        this.title = title;

    }

    public Book(String title, double price) {

        System.out.println("一个新的Book类对象产生。"); // 把这行语句想象成50行代码

        this.title = title;

        this.price = price;

    }

    // settergetter

    public String getInfo() {

        return "书名:" + this.title + ",价格:" + this.price;

    }

}

public class TestDemo {

    public static void main(String args[]) {

        Book book = new Book("Java开发", 89.2);

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

    }

}

范例1-74:消除掉构造方法中的重复代码。

class Book {

    private String title;

    private double price;

    public Book() {

        System.out.println("一个新的Book类对象产生。"); // 把这行语句想象成50行代码

    }

    public Book(String title) {

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

        this.title = title;

    }

    public Book(String title, double price) {

        this(title) ; // 调用本类有一个参数的构造方法

        this.price = price;

    }

    // settergetter

    public String getInfo() {

        return "书名:" + this.title + ",价格:" + this.price;

    }

}

public class TestDemo {

    public static void main(String args[]) {

        Book book = new Book("Java开发", 89.2);

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

    }

}

范例1-75:观察错误的代码。

class Book {

    private String title;

    private double price;

    public Book() {

        this("HELLO", 1.1);  // 调用双参构造

        System.out.println("一个新的Book类对象产生。");

    }

    public Book(String title) {

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

        this.title = title;

    }

    public Book(String title, double price) {

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

        this.price = price;

    }

    // settergetter

    public String getInfo() {

        return "书名:" + this.title + ",价格:" + this.price;

    }

}

范例1-76:直接输出对象。

class Book {

    public void print() { // 调用print()方法的对象就是当前对象,this就自动与此对象指向同一块内存地址

        System.out.println("this = " + this); // this就是当前调用方法的对象

    }

}

public class TestDemo {

    public static void main(String args[]) {

        Book booka = new Book(); // 实例化新的Book类对象

        System.out.println("booka = " + booka); // 主方法中输出Book类对象

        booka.print(); // 调用Book类的print()方法输出此时booka为当前对象

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

        Book bookb = new Book(); // 实例化新的Book类对象

        System.out.println("bookb = " + bookb); // 主方法中输出Book类对象

        bookb.print(); // 调用Book类的print()方法输出此时bookb为当前对象

    }

}

1.11  引用传递

范例1-77:第一道引用传递范例。

class Message {

    private int num = 10; // 定义int基本类型的属性

    /**

     * 本类没有提供无参构造方法而是提供有参构造可以接收num属性的内容

     * @param num 接收num属性的内容

     */

    public Message(int num) {

        this.num = num; // num属性赋值

    }

    public void setNum(int num) {

        this.num = num;

    }

    public int getNum() {

        return this.num;

    }

}

public class TestDemo {

    public static void main(String args[]) {

        Message msg = new Message(30); // 实例化Message类对象同时传递num属性内容

        fun(msg); // 引用传递

        System.out.println(msg.getNum()); // 输出num属性内容

    }

    /**

     * 修改Message类中的num属性内容

     * @param temp Message类的引用

     */

    public static void fun(Message temp) {

        temp.setNum(100); // 修改num属性内容

    }

}

范例1-78:第二道引用范例。

public class TestDemo {

    public static void main(String args[]) {

        String msg = "Hello"; // 定义String类对象

        fun(msg); // 引用传递

        System.out.println(msg); // 输出msg对象内容

    }

    public static void fun(String temp) { // 接收字符串引用

        temp = "World"; // 改变字符串引用

    }

}

范例1-79:实现int数据的接收。

public class TestDemo {

    public static void main(String args[]) {

        int msg = 10 ; // 基本数据类型

        fun(msg); // 数值传递

        System.out.println(msg); // 输出msg变量内容

    }

    public static void fun(int temp) { // 接收数据内容

        temp = 100; // 改变变量内容

    }

}

范例1-80:第三道引用传递。

class Message {

    private String info = "此内容无用" ; // 定义String类型属性

    public Message(String info) { // 利用构造方法设置info属性内容

        this.info = info ;

    }

    public void setInfo(String info) {

        this.info = info ;

    }

    public String getInfo() {

        return this.info ;

    }

}

public class TestDemo {

    public static void main(String args[]) {

        Message msg = new Message("Hello") ; // 实例化Message类对象

        fun(msg) ; // 引用传递

        System.out.println(msg.getInfo()) ; // 输出info属性内容

    }

    public static void fun(Message temp) { // 接收Message类引用

        temp.setInfo("World") ; // 修改info属性内容

    }

}

范例1-81:数据库创建脚本。

CREATE TABLE member( 

    mid NUMBER ,

    name VARCHAR2(50) ,

    CONSTRAINT pk_mid PRIMARY KEY(mid)

) ;

CREATE TABLE car(

    mid NUMBER ,

    pname VARCHAR2(50) ,

    CONSTRAINT fk_mid FOREIGN KEY(mid) REFERENCES member(mid) ,

    CONSTRAINT pk_mid2 PRIMARY KEY(mid)

) ;

范例1-82:代码实现(无参构造、setter、getter略,同时本程序定义的是两个简单Java类)。

class Member {

    private int mid; // 人员编号

    private String name; // 人员姓名

    private Car car; // 表示属于人的车如果没有车则内容为null

    public Member(int mid, String name) {

        this.mid = mid;

        this.name = name;

    }

    public void setCar(Car car) {

        this.car = car ;

    }

    public Car getCar() {

        return this.car ;

    }

    public String getInfo() {

        return "人员编号:" + this.mid + ",姓名:" + this.name;

    }

}

class Car {

    private Member member; // 车属于一个人如果没有所属者则为null

    private String pname; // 车的名字

    public Car(String pname) {

        this.pname = pname;

    }

    public void setMember(Member member) {

        this.member = member ;

    }

    public Member getMember() {

        return this.member ;

    }

    public String getInfo() {

        return "车的名字:" + this.pname;

    }

}

范例1-83:代码测试。

public class TestDemo {

    public static void main(String args[]) {

        // 第一步:根据既定结构设置数据

        Member m = new Member(1,"李兴华") ; // 独立对象

        Car c = new Car("八手奥拓100") ; // 独立对象

        m.setCar(c) ; // 一个人有一辆车

        c.setMember(m) ; // 一辆车属于一个人

        // 第二步:根据既定结构取出关系

        System.out.println(m.getCar().getInfo()) ; // 通过人找到车的信息

        System.out.println(c.getMember().getInfo()) ; // 通过车找到人的信息

    }

}

范例1-84:修改Member类定义。

class Member {

    private int mid; // 人员编号

    private String name; // 人员姓名

    private Car car; // 表示属于人的车如果没有车则内容为null

    private Member child ; // 表示人的孩子如果没有则为null

    public Member(int mid, String name) {

        this.mid = mid;

        this.name = name;

    }

    public void setCar(Car car) {

        this.car = car ;

    }

    public Car getCar() {

        return this.car ;

    }

    public void setChild(Member child) {

        this.child = child;

    }

    public Member getChild() {

        return child;

    }

    public String getInfo() {

        return "人员编号:" + this.mid + ",姓名:" + this.name;

    }

}

class Car {

    private Member member; // 车属于一个人如果没有所属者则为null

    private String pname; // 车的名字

    public Car(String pname) {

        this.pname = pname;

    }

    public void setMember(Member member) {

        this.member = member ;

    }

    public Member getMember() {

        return this.member ;

    }

    public String getInfo() {

        return "车的名字:" + this.pname;

    }

}

public class TestDemo {

    public static void main(String args[]) {

        // 第一步根据既定结构设置数据

        Member m = new Member(1,"李兴华") ; // 独立对象

        Member chd = new Member(2,"") ;   // 独立对象

        Car c = new Car("八手奥拓100") ; // 独立对象

        Car cc = new Car("法拉利M9") ; // 一辆车

        m.setCar(c) ; // 一个人有一辆车

        c.setMember(m) ; // 一辆车属于一个人

        chd.setCar(cc) ; // 一个孩子有一辆车

        cc.setMember(chd) ; // 一个车属于一个孩子

        m.setChild(chd) ; // 一个人有一个孩子

        // 第二步根据既定结构取出关系

        System.out.println(m.getCar().getInfo()) ; // 通过人找到车的信息

        System.out.println(c.getMember().getInfo()) ; // 通过车找到人的信息

        System.out.println(m.getChild().getInfo()) ; // 通过人找到他孩子的信息

        System.out.println(m.getChild().getCar().getInfo()) ; // 通过人找到他孩子的车的信息

    }

}

范例1-85:描述电脑组成关系。

class 键盘{}

class 鼠标{}

class CPU{}

class 硬盘{}

class 内存{}

class 显示器{}

class 主板 {}

class 主机 {

    private CPU 对象1 [] ;

    private 硬盘 对象2 [] ;

    private 主板 对象3 ;

    private 内存 对象4 [] ;

}

class 计算机 {

    private 主机 对象1 ;

    private 显示器 对象2 [] ;

    private 键盘 对象3 ;

    private 鼠标 对象4 ;

}

1.12  数据表与简单Java类映射

范例1-86:代码实现。

class Dept {

   private int deptno; // 部门编号

   private String dname; // 部门名称

   private String loc; // 部门位置

   private Emp emps [] ; // 多个雇员 

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

      this.deptno = deptno;

      this.dname = dname;

      this.loc = loc;

   }

   // settergetter、无参构造略

   public String getInfo() {

      return "部门编号:" + this.deptno + ",名称:" + this.dname + ",位置:" + this.loc;

   }

}

class Emp {

   private int empno; // 雇员编号

   private String ename; // 雇员姓名

   private String job; // 雇员职位

   private double sal; // 基本工资

   private double comm; // 佣金

   private Dept dept ;

   private Emp mgr; // 表示雇员对应的领导

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

      this.empno = empno;

      this.ename = ename;

      this.job = job;

      this.sal = sal;

      this.comm = comm;

   }

   // settergetter、无参构造略

   public String getInfo() {

      return "雇员编号:" + this.empno + ",姓名:" + this.ename + ",职位:" + this.job

             + ",工资:" + this.sal + ",佣金:" + this.comm;

   }

}

范例1-87:设置并取得数据。

public class TestDemo {

    public static void main(String args[]) {

        // 第一步:根据表结构描述设置数据

        // 1产生各自的独立对象

        Dept dept = new Dept(10,"ACCOUNTING","New York") ; // 部门信息

        Emp ea = new Emp(7369,"SMITH","CLERK",800.0,0.0) ; // 雇员信息

        Emp eb = new Emp(7902,"FORD","MANAGER",2450.0,0.0) ; // 雇员信息

        Emp ec = new Emp(7839,"KING","PRESIDENT",5000.0,0.0) ; // 雇员信息

        // 2设置雇员和领导关系

        ea.setMgr(eb) ; // 设置雇员领导

        eb.setMgr(ec) ; // 设置雇员领导

        // 3设置雇员和部门关系

        ea.setDept(dept) ; // 雇员与部门

        eb.setDept(dept) ; // 雇员与部门

        ec.setDept(dept) ; // 雇员与部门

        dept.setEmps(new Emp[]{ea,eb,ec}) ; // 部门与雇员

        // 第步:根据表结构描述取得设置的数据

        System.out.println(ea.getInfo()) ; // 取得雇员信息

        System.out.println("\t|- " + ea.getMgr().getInfo()) ; // 取得雇员领导信息

        System.out.println("\t|- " + ea.getDept().getInfo()) ; // 取得雇员部门信息

        // 取得部门的完整信息,包括部门基础信息以及部门中的所有员工和每个员工的领导信息

        System.out.println(dept.getInfo()) ; // 部门信息

        for (int x = 0 ; x < dept.getEmps().length ; x ++) { // 所有雇员信息

            System.out.println("\t|- " + dept.getEmps()[x].getInfo()) ; // 雇员信息

            if (dept.getEmps()[x].getMgr() != null) { // 判断是否存在领导信息

              System.out.println("\t\t|- " +

                       dept.getEmps()[x].getMgr().getInfo()); // 领导信息

            }

        }

    }

}

1.13  对象比较

范例1-88:基础的比较方式。

class Book {

    private String title;

    private double price;

    public Book(String title, double price) {

        this.title = title;

        this.price = price;

    }

    public String getTitle() {

        return this.title;

    }

    public double getPrice() {

        return this.price;

    }

}

public class TestDemo {

    public static void main(String args[]) {

        Book b1 = new Book("Java开发", 79.8); // 实例化Book类对象

        Book b2 = new Book("Java开发", 79.8); // 实例化Book类对象

        if (b1.getTitle().equals(b2.getTitle())

              && b1.getPrice() == b2.getPrice()) { // 属性比较

           System.out.println("是同一个对象!");

        } else {

           System.out.println("不是同一个对象!");

        }

    }

}

范例1-89:观察封装属性的进一步操作。

class Info {

    private String msg = "Hello";

    public void print() {

        System.out.println("msg = " + msg);

    }

    public void fun(Info temp) { // 本类接收本类对象

        temp.msg = "修改内容"; // 在类的内部直接利用对象访问私有属性

    }

}

public class Demo {

    public static void main(String args[]) {

        Info x = new Info();

        x.fun(x); // 没有意义,只是一个语法验证

        x.print();

    }

}

范例1-90:对象比较实现。

class Book {

    private String title ;

    private double price ;

    public Book(String title,double price) {

        this.title = title ;

        this.price = price ;

    }

    /**

     * 进行本类对象的比较操作,在比较过程中首先会判断传入的对象是否为null,后判断地址是否相同

     * 如果都不相同则进行对象内容的判断,由于compare()方法接收了本类引用,所以可以直接访问私有属性

     * @param book 要进行判断的数据

     * @return 内存地址相同或者属性完全相同返回true,否则返回false

     */

    public boolean compare(Book book) {

        if (book == null) { // 传入数据为null

           return false ; // 没有必要进行具体的判断

        }

        // 执行“b1.compare(b2)”代码时会有两个对象

        // 当前对象this(调用方法对象,就是b1引用)

        // 传递的对象book(引用传递,就是b2引用)

        if (this == book) { // 内存地址相同

           return true ; // 避免进行具体细节的比较,节约时间

        }

        if (this.title.equals(book.title)

           && this.price == book.price) { // 属性判断

           return true ;

        } else {

           return false ;

        }

    }

    // settergetter

}

public class TestDemo {

    public static void main(String args[]) {

        Book b1 = new Book("Java开发",79.8) ; // 实例化Book类对象

        Book b2 = new Book("Java开发",79.8) ; // 实例化Book类对象

        if (b1.compare(b2)) { // 对象比较 

           System.out.println("是同一个对象!") ;

        } else {

           System.out.println("不是同一个对象!") ;

        }

    }

}

1.14  static关键字

范例1-91:定义程序。

class Book { // 描述的是同一个出版社的信息

    private String title ; // 普通属性

    private double price ; // 普通属性

    static String pub = "清华大学出版社" ;   // 定义一个描述出版社信息的属性操作方便暂不封装

    public Book(String title,double price) {

        this.title = title ;

        this.price = price ;

    }

    public String getInfo() {

        return "图书名称:" + this.title + ",价格:" + this.price + ",出版社:" + this.pub ;

    }

}

public class TestDemo {

    public static void main(String args[]) {

        Book ba = new Book("Java开发",10.2) ; // 实例化Book类对象

        Book bb = new Book("Android开发",11.2) ; // 实例化Book类对象

        Book bc = new Book("Oracle开发",12.2) ; // 实例化Book类对象

        ba.pub = "北京大学出版社" ; // 修改了一个属性的内容

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

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

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

    }

}

范例1-92:在没有实例化对象产生时直接操作static属性。

public class TestDemo {

    public static void main(String args[]) {

        System.out.println(Book.pub) ; // 在没有实例化对象的情况下直接输出属性内容

        Book.pub = "北京大学出版社" ; // 修改static属性内容

        Book ba = new Book("Java开发",10.9) ; // 实例化Book类对象

        System.out.println(ba.getInfo()) ; // 输出Book类对象信息

    }

}

范例1-93:使用static定义方法。

class Book { // 描述的是同一个出版社的信息

    private String title ;

    private double price ;

    private static String pub = "清华大学出版社" ;  // 定义一个描述出版社信息的属性

    public Book(String title,double price) {

        this.title = title ;

        this.price = price ;

    }

    public static void setPub(String p) { // 定义static方法可以由类名称直接调用

        pub = p ;

    }

    public String getInfo() {

        return "图书名称:" + this.title + ",价格:" + this.price + ",出版社:" + this.pub ;

    }

}

public class TestDemo {

    public static void main(String args[]) {

        Book.setPub("北京大学出版社") ; // 在没有对象产生的时候进行调用

        Book ba = new Book("Java开发",10.2) ; // 实例化Book类对象

        Book bb = new Book("Android开发",11.2) ; // 实例化Book类对象

        Book bc = new Book("Oracle开发",12.2) ; // 实例化Book类对象

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

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

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

    }

}

范例1-94:观察如下代码。

public class TestDemo {

    public static void main(String args[]) { // static定义的方法

        fun(); // static方法调用static方法

    }

    public static void fun() { // static定义的方法

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

    }

}

范例1-95:不使用static声明方法。

public class TestDemo {

    public static void main(String args[]) { // static定义的方法

        new TestDemo().fun(); // 对象调用方法

    }

    public void fun() { // static定义的方法

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

    }

}

范例1-96:定义一个数学的加法操作。

class MyMath { // 数学操作类类中没有属性

    public static int add(int x, int y) { // 只是一个加法操作

        return x + y;

    }

}

public class TestDemo {

    public static void main(String args[]) {

        System.out.println(MyMath.add(10, 20)); // 直接调用

    }

}

范例1-97:得到参数。

public class TestDemo {

    public static void main(String args[]) {

        for (int x = 0; x < args.length; x++) { // 循环输出参数

            System.out.println(args[x]);

        }

    }

}

1.15  代码块

范例1-98:编写普通代码块。

public class TestDemo {

    public static void main(String args[]) {

        { // 普通代码块

            int num = 10; // 局部变量

            System.out.println("num = " + num);

        }

        int num = 100; // 全局变量

        System.out.println("num = " + num);

    }

}

范例1-99:说明代码。

public class TestDemo {

    private static int num = 100 ; // 全局变量

    public static void main(String args[]) {

        int num = 100; // 局部变量

    }

}

范例1-100:定义构造块。

class Book {

    public Book() { // 构造方法

        System.out.println("ABook类的构造方法");

    }

    { // 将代码块写在类里所以为构造块

        System.out.println("BBook类中的构造块");

    }

}

public class TestDemo {

    public static void main(String args[]) {

        new Book(); // 实例化类对象

        new Book(); // 实例化类对象

    }

}

范例1-101:利用静态块为static属性初始化。

class Book {

    static String msg ; // static属性暂不封装

    public Book() { // 构造方法

        System.out.println("ABook类的构造方法");

    }

    { // 将代码块写在类里,所以为构造块

        System.out.println("【B】Book类中的构造块");

    }

    static { // 定义静态块

        msg = "Hello".substring(0,2) ;

        System.out.println("【C】Book类中的静态块") ;

    }

}

public class TestDemo {

    public static void main(String args[]) {

        new Book(); // 实例化类对象

        new Book(); // 实例化类对象

        System.out.println(Book.msg) ;

    }

}

范例1-102:JDK 1.7之前的Bug。

public class TestDemo {

    static {

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

        System.exit(1);

    }

}

1.16  内部类

范例1-103:观察内部类的基本形式。

class Outer { // 外部类

    private String msg = "Hello World !";

    class Inner { // 定义一个内部类

        public void print() {

            System.out.println(msg);

        }

    }

    public void fun() {

        new Inner().print(); // 实例化内部类对象并且调用print()方法

    }

}

public class TestDemo {

    public static void main(String args[]) {

        Outer out = new Outer(); // 实例化外部类对象

        out.fun(); // 调用外部类方法

    }

}

范例1-104:将内部类放到外部并且实现同样功能。

class Outer { // 外部类

    private String msg = "Hello World !" ;

    public void fun() {

        // this表示当前调用fun()方法的对象在本程序中主方法由out对象调用所以this就是out

        new Inner(this).print() ; // 实例化内部类对象并且调用print()方法

    }

    // 内部类需要访问msg属性但是此属性属于Outer而在Outer类里面此属性使用private进行封装

    // 所以如果此时要得到这个属性的内容,需要定义一个getter方法

    public String getMsg() {

        return this.msg ;

    }

}

class Inner { // 定义一个内部类

    private Outer out ; // 必须依靠对象才可以调用getMsg()方法

    public Inner(Outer out) { // 在构造方法中接收外部类对象

        this.out = out ;

    }

    public void print() { // 利用Outer类对象调用方法

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

    }

}

public class TestDemo {

    public static void main(String args[]) {

        Outer out = new Outer() ; // 实例化外部类对象

        out.fun() ; // 调用外部类方法

    }

}

范例1-105:访问内部类的私有属性。

class Outer { // 外部类

    private String msg = "Hello World !" ;

    class Inner { // 定义一个内部类

        private String info = "世界你好!" ; // 内部类的私有属性

        public void print() {

            System.out.println(msg) ; // 直接访问外部类的私有属性

        }

    }

    public void fun() {

        Inner in = new Inner() ; // 内部类对象

        System.out.println(in.info) ; // 直接利用内部类对象访问内部类中定义的私有属性

    }

}

public class TestDemo {

    public static void main(String args[]) {

        Outer out = new Outer() ; // 实例化外部类对象

        out.fun() ; // 调用外部类方法

    }

}

范例1-106:使用this访问外部类属性。

class Outer { // 外部类

    private String msg = "Hello World !" ;

    class Inner { // 定义一个内部类

        public void print() {

            System.out.println(Outer.this.msg) ; // 外部类.this = 外部类当前对象

        }

    }

}

范例1-107:实例化内部类对象。

class Outer { // 外部类

    private String msg = "Hello World !" ;

    class Inner { // 定义一个内部类

        public void print() {

            System.out.println(Outer.this.msg) ;

        }

    }

}

public class TestDemo {

    public static void main(String args[]) {

        Outer.Inner in = new Outer().new Inner() ; // 实例化内部类对象

        in.print() ;

    }

}

范例1-108:定义私有内部类

class Outer { // 外部类

    private String msg = "Hello World !" ;

    private class Inner { // 定义私有内部类

        public void print() {

            System.out.println(Outer.this.msg) ;

        }

    }

}

范例1-109:利用static定义内部类。

class Outer { // 外部类

    private static String msg = "Hello World !"; // static属性

    static class Inner { // static定义的内部类等同于外部类

        public void print() {

            System.out.println(Outer.msg); // 直接访问static属性

        }

    }

}

范例1-110:实例化“外部类”对象。

class Outer { // 外部类

    private static String msg = "Hello World !"; // static属性

    static class Inner { // static定义的内部类等同于外部类

        public void print() {

        System.out.println(Outer.msg); // 直接访问static属性

        }

    }

}

public class TestDemo {

    public static void main(String args[]) {

        Outer.Inner in = new Outer.Inner() ; // 实例化“外部类”对象

        in.print() ; // 调用方法

    }

}

范例1-111:在普通方法里面定义内部类。

class Outer { // 外部类

    private String msg = "Hello World !" ;

    public void fun() { // 外部类普通方法

        class Inner { // 方法中定义的内部类

            public void print() {

               System.out.println(Outer.this.msg) ;

            }

        }

        new Inner().print() ; // 内部类实例化对象调用print()输出

    }

}

public class TestDemo {

    public static void main(String args[]) {

        new Outer().fun() ;

    }

}

范例1-112:访问方法中定义的参数或变量。

class Outer { // 外部类

    private String msg = "Hello World !" ;

    public void fun(int num) { // 外部类普通方法

        double score = 99.9 ; // 方法变量

        class Inner { // 方法中定义的内部类

            public void print() {

               System.out.println("属性:" + Outer.this.msg) ;

               System.out.println("方法参数:" + num) ;

               System.out.println("方法变量:" + score) ;

            }

        }

        new Inner().print() ; // 内部类实例化对象调用print()输出

    }

}

public class TestDemo {

    public static void main(String args[]) {

        new Outer().fun(100) ;

    }

}

范例1-113:JDK 1.7之前的代码。

class Outer { // 外部类

    private String msg = "Hello World !" ;

    public void fun(final int num) { // 外部类普通方法

        final double score = 99.9 ; // 方法变量

        class Inner { // 方法中定义的内部类

            public void print() {

                System.out.println("属性:" + Outer.this.msg) ;

                System.out.println("方法参数:" + num) ;

                    System.out.println("方法变量:" + score) ;

            }

        }

        new Inner().print() ; // 内部类实例化对象调用print()输出

    }

}

1.17  链表

范例1-114:定义一个Node类。

class Node { // 每一个链表实际上就是由多个节点组成的

    private String data; // 要保存的数据

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

    /**

     * 每一个Node类对象都必须保存有相应的数据

     * @param data 要通过节点包装的数据

     */

    public Node(String data) { // 必须有数据才有Node

        this.data = data;

    }

    /**

     * 设置下一个节点关系

     * @param next 保存下一个Node类引用

     */

    public void setNext(Node next) {

        this.next = next;

    }

    /**

     * 取得当前节点的下一个节点

     * @return 当前节点的下一个节点引用

     */

    public Node getNext() {

        return this.next;

    }

    /**

     * 设置或修改当前节点包装的数据

     * @param data

     */

    public void setData(String data) {

        this.data = data;

    }

    /**

     * 取得包装的数据

     * @return

     */

    public String getData() {

        return this.data;

    }

}

范例1-115:手工配置节点关系,并使用while循环输出全部节点数据。

public class LinkDemo {

    public static void main(String args[]) {

        // 第一步:定义要操作的节点设置好包装的字符串数据

        Node root = new Node("火车头") ; // 定义节点,同时包装数据

        Node n1 = new Node("车厢A") ; // 定义节点,同时包装数据

        Node n2 = new Node("车厢B") ; // 定义节点,同时包装数据

        root.setNext(n1) ; // 设置节点关系

        n1.setNext(n2) ; // 设置节点关系

        // 第二:根据节点关系取出所有数据

        Node currentNode = root ; // 当前从根节点开始读取

        while (currentNode != null) { // 当前节点存在数据

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

            currentNode = currentNode.getNext() ; // 将下一个节点设置为当前节点

        }

    }

}

范例1-116:手工配置节点关系,通过递归输出全部节点数据。

public class LinkDemo {

     public static void main(String args[]) {

          // 第一步:定义要操作的节点设置好包装的字符串数据

          Node root = new Node("火车头") ; // 定义节点,同时包装数据

          Node n1 = new Node("车厢A") ; // 定义节点,同时包装数据

          Node n2 = new Node("车厢B") ; // 定义节点,同时包装数据

          root.setNext(n1) ; // 设置节点关系

          n1.setNext(n2) ; // 设置节点关系

          print(root) ; // 由根节点开始输出

     }

     /**

      * 利用递归方式输出所有的节点数据

      * @param current

      */

     public static void print(Node current) { // 第二步:根据节点关系取出所有数据

          if (current == null) { // 递归结束条件

             return; // 结束方法

          }

          System.out.println(current.getData()); // 输出节点包含的数据

          print(current.getNext()); // 递归操作

     }

}

范例1-117:链表的基本形式。

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;

    }

    /**

     * 实现节点的添加(递归调用,目的是将新节点保存到最后一个节点之后)

     * 第一次调用(Link):this = Link.root

     * 第二次调用(Node):this = Link.root.next

     * 第三次调用(Node):this = Link.root.next.next

     * @param newNode 新节点,节点对象由Link类创建

     */

    public void addNode(Node newNode) {

        if (this.next == null) { // 当前节点的下一个为null

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

        } else { // 当前节点之后还存在节点

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

        }

    }

    /**

     * 递归的方式输出每个节点保存的数据

     * 第一次调用(Link):this = Link.root

     * 第二次调用(Node):this = Link.root.next

     * 第三次调用(Node):this = Link.root.next.next

     */

    public void printNode() {

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

        if (this.next != null) { // 还有下一个节点

           this.next.printNode(); // 找到下一个节点继续输出

        }

    }

}

class Link { // 负责数据的设置和输出

    private Node root; // 根节点

    /**

     * 向链表中增加新的数据,如果当前链表没有节点则第一个数据作为节点

     * 如果有节点则使用Node类将新节点保存到最后一个节点之后

     * @param data 要保存的数据

     */

    public void add(String data) {

        Node newNode = new Node(data); // 置数据的先后关系,所以将data包装在一个Node类对象

        if (this.root == null) { // 一个链表只有一个根节点

           this.root = newNode; // 将新的节点设置为根节点

        } else { // 根节点已经存在

           this.root.addNode(newNode); // 交由Node类来进行节点保存

        }

    }

    /**

     * 使用递归方式,输出节点中的全部数据

     */

    public void print() { // 输出数据

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

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

        }

    }

}

public class LinkDemo {

    public static void main(String args[]) {

        Link link = new Link(); // 由这个类负责所有的数据操作

        link.add("Hello"); // 存放数据

        link.add("MLDN"); // 存放数据

        link.add("YOOTK"); // 存放数据

        link.add("李兴华"); // 存放数据

        link.print(); // 展示数据

    }

}

范例1-118:链表的基本开发结构。

class Link { // 链表类外部能够看见的只有这一个类

    private class Node { // 定义的内部节点类

        private String data; // 要保存的数据

        private Node next; // 下一个节点引用

        public Node(String data) { // 每一个Node类对象都必须保存相应的数据

            this.data = data;

        }

    }

    // ===================== 以上为内部类 ===================

    private Node root; // 根节点定义

}

范例1-119:修改Link.java类。

—  增加一个count属性,保存元素个数;

    private int count = 0 ; // 保存元素的个数

—  在add()方法里面增加数据的统计操作;

    /**

     * 用户向链表增加新的数据,在增加时要将数据封装为Node类,这样才可以匹配节点顺序

     * @param data 要保存的数据

     */

    public void add(String data) { // 假设不允许有null

        if (data == null) { // 判断数据是否为空

           return; // 结束方法调用

        }

        Node newNode = new Node(data); // 要保存的数据

        if (this.root == null) { // 当前没有根节点

           this.root = newNode; // 保存根节点

        } else { // 根节点存在

           this.root.addNode(newNode); // 交给Node类处理节点的保存

        }

        this.count ++ ; // 数据保存成功后保存个数加一

    }

—  随后为Link类增加一个新的方法:size()。

    /**

     * 取得链表中保存的数据个数

     * @return 保存的个数,通过count属性取得

     */

    public int size() { // 取得保存的数据量

        return this.count;

    }

范例1-120:判断是否为空链表。

    /**

     * 判断是否是空链表,表示长度为0,不是null

     * @return 如果链表中没有保存任何数据则返回true,否则返回false

     */

    public boolean isEmpty() {

        return this.count == 0;

    }

范例1-121:在Node类增加方法。

        /**

         * 数据检索操作,判断指定数据是否存在

         * 第一次调用(Link):this = Link.root

         * 第二次调用(Node):this = Link.root.next

         * @param data 要查询的数据

         * @return 如果数据存在返回true,否则返回false

         */

        public boolean containsNode(String data) {

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

               return true; // 后面不再查询

            } else { // 当前节点数据不满足查询要求

                if (this.next != null) { // 有后续节点

                  return this.next.containsNode(data); // 递归调用继续查询

                } else { // 没有后续节点

                  return false; // 没有查询到返回false

                }

            

        }

范例1-122:修改Link。

    /**

     * 数据查询操作,判断指定数据是否存在,如果链表没有数据直接返回false

     * @param data 要判断的数据

     * @return 数据存在返回true,否则返回false

     */

    public boolean contains(String data) {

        if (data == null || this.root == null) { // 现在没有要查询的数据根节点也不保存数据

           return false ; // 没有查询结果

        }

        return this.root.containsNode(data) ; // 交由Node类查询

    }

范例1-123:定义测试程序。

public class LinkDemo {

    public static void main(String args[]) {

        Link all = new Link(); // 创建链表对象

        all.add("yootk"); // 保存数据

        all.add("mldn"); // 保存数据

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

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

    }

}

范例1-124:在Link类里面增加一个foot的属性,表示每一个Node元素的编号。

    private int foot = 0 ; // 节点索引

范例1-125:在每一次查询时(一个链表可能查询多次),foot应该都从头开始计算(foot设为0)。

    /**

     * 根据索引取得保存的节点数据

     * @param index 索引数据

     * @return 如果要取得的索引内容不存在或者大于保存个数返回null,反之返回数据

     */

    public String get(int index) {

        if (index > this.count) { // 超过了查询范围

           return null ; // 没有数据

        }

        this.foot = 0 ; // 表示从前向后查询

        return this.root.getNode(index) ; // 查询过程交给Node

    }

范例1-126:在Node类里面实现getNode()方法,内部类和外部类之间可以方便地进行私有属性的互相访问。

        /**

         * 根据索引取出数据,此时该索引一定是存在的

         * @param index 要取得数据的索引编号

         * @return 返回指定索引节点包含的数据

         */

        public String getNode(int index) {

            // 使用当前的foot内容与要查询的索引进行比较,随后将foot的内容自增,目的是下次查询方便

            if (Link.this.foot++ == index) { // 当前为要查询的索引

               return this.data; // 返回当前节点数据

            } else { // 继续向后查询

               return this.next.getNode(index); // 进行下一个节点的判断

            }

        }

范例1-127:在Node类里面增加setNode()方法。

        /**

         * 修改指定索引节点包含的数据

         * @param index 要修改的索引编号

         * @param data 新数据

         */

        public void setNode(int index, String data) {

            // 使用当前的foot内容与要查询的索引进行比较,随后将foot的内容自增,目的是下次查询方便

            if (Link.this.foot++ == index) { // 当前为要修改的索引

               this.data = data; // 进行内容的修改

            } else {

               this.next.setNode(index, data); // 继续下一个节点的索引判断

            }

        }

范例1-128:在Link类里面增加set()方法。

    /**

     * 根据索引修改数据

     * @param index 要修改数据的索引编号

     * @param data 新的数据内容

     */

    public void set(int index, String data) {

        if (index > this.count) { // 判断是否超过了保存范围

           return; // 结束方法调用

        }

        this.foot = 0; // 重新设置foot属性的内容作为索引出现

        this.root.setNode(index, data); // 交给Node类设置数据内容

    }

范例1-128:在Node类里面增加一个removeNode()方法,此方法专门负责处理非根节点的删除。

        /**

         * 节点的删除操作,匹配每一个节点的数据,如果当前节点数据符合删除数据

         * 则使用“当前节点上一节点.next = 当前节点.next”方式空出当前节点

         * 第一次调用(Link): previous = Link.root、this = Link.root.next

         * 第二次调用(Node): previous = Link.root.next、this = Link.root.next.next

         * @param previous 当前节点的上一个节点

         * @param data 要删除的数据

         */

        public void removeNode(Node previous, String data) {

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

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

            } else { // 应该向后继续查询

               this.next.removeNode(this, data); // 继续下一个判断

            }

        }

范例1-129:在Link类里面增加根节点的判断。

    /**

     * 链表数据的删除操作,在删除前要先使用contains()判断链表中是否存在指定数据

     * 如果要删除的数据存在则首先判断根节点的数据是否为要删除数据

     * 如果是则将根节点的下一个节点作为新的根节点

     * 如果要删除的数据不是根节点数据,则将删除操作交由Node类的removeNode()方法完成

     * @param data 要删除的数据

     */

    public void remove(String data) {

        if (this.contains(data)) { // 主要功能是判断数据是否存在

            // 要删除数据是否是根节点数据,root是Node类的对象,此处直接访问内部类的私有操作

            if (data.equals(this.root.data)) { // 根节点数据为要删除数据

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

            } else { // 根节点数据不是要删除数据

               // 此时根元素已经判断过了,从第二个元素开始判断,即第二个元素的上一个元素为根节点

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

            }

            this.count--; // 删除成功后个数要减少

        }

    }

范例1-130:修改Link类的定义。

—  增加一个返回的数组属性内容,之所以将其定义为属性,是因为内部类和外部类都可以访问;

    private String [] retArray ; // 返回的数组

—  增加toArray()方法。

    /**

     * 将链表中的数据转换为对象数组输出

     * @return 如果链表没有数据返回null,如果有数据则将数据变为对象数组后返回

     */

    public String[] toArray() {

        if (this.root == null) { // 判断链表是否有数据

           return null; // 没有数据返回null

        }

        this.foot = 0; // 脚标清零操作

        this.retArray = new String[this.count]; // 根据保存内容开辟数组

        this.root.toArrayNode(); // 交给Node类处理

        return this.retArray; // 返回数组对象

    }

范例1-131:在Node类里面处理数组数据的保存。

        /**

         * 将节点中保存的内容转化为对象数组

         * 第一次调用(Link):this = Link.root;

         * 第二次调用(Node):this = Link.root.next

         */

        public void toArrayNode() {

            Link.this.retArray[Link.this.foot++] = this.data; // 取出数据并保存在数组中

            if (this.next != null) { // 有后续元素

               this.next.toArrayNode(); // 继续下一个数据的取得

            }

        }

范例1-132:清空链表。

    public void clear() {

        this.root = null; // 清空链表

        this.count = 0; // 元素个数为0

    }

范例1-133:定义一个保存图书信息的类。

class Book {

    private String title ;

    private double price ;

    public Book(String title,double price) {

        this.title = title ;

        this.price = price ;

    }

    /**

     * 进行本类对象的比较操作,在比较过程中首先会判断传入的对象是否为null,而后判断地址是否相同

     * 如果都不相同则进行对象内容的判断,由于compare()方法接收了本类引用,所以可以直接访问私有属性

     * @param book 要进行判断的数据

     * @return 内存地址相同或属性完全相同返回true,否则返回false

     */

    public boolean compare(Book book) {

        if (book == null) { // 传入数据为null

           return false ; // 没有必要进行具体的判断

        }

        // 执行“b1.compare(b2)”代码时会有两个对象

        // 当前对象this(调用方法对象,就是b1引用)

        // 传递的对象book(引用传递,就是b2引用)

        if (this == book) { // 内存地址相同

           return true ; // 避免进行具体细节的比较,节约时间

        }

        if (this.title.equals(book.title)

           && this.price == book.price) { // 属性判断

           return true ;

        } else {

           return false ;

        }

    }

    // setter、getter略

    public String getInfo() {

        return "图书名称:" + this.title + ",图书价格:" + this.price ;

    }

}

范例1-134:修改链表实现(本代码主要是将之前的链表类中的String类型更换为Book类型,对象比较更换为compare()方法)。

class Link { // 链表类外部能够看见的只有这一个类

    private class Node { // 定义的内部节点类

        private Book data; // 要保存的数据

        private Node next; // 下一个节点引用

        public Node(Book data) { // 每一个Node类对象都必须保存相应的数据

            this.data = data;

        }

        /**

         * 设置新节点的保存所有的新节点保存在最后一个节点之后

         * @param newNode 新节点对象

         */

        public void addNode(Node newNode) {

            if (this.next == null) { // 当前的下一个节点为null

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

            } else { // 向后继续保存

               this.next.addNode(newNode) ;

            }

        }

        /**

             * 数据检索操作判断指定数据是否存在

         * 第一次调用(Link):this = Link.root

         * 第二次调用(Node):this = Link.root.next

         * @param data 要查询的数据

         * @return 如果数据存在返回true,否则返回false

         */

        public boolean containsNode(Book data) {

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

               return true; // 后面不再查询了

            } else { // 当前节点数据不满足查询要求

               if (this.next != null) { // 有后续节点

                  return this.next.containsNode(data); // 递归调用继续查询

               } else { // 没有后续节点

                 return false; // 没有查询到返回false

               }

            }

        }

        /**

         * 根据索引取出数据,此时该索引一定是存在的

         * @param index 要取得数据的索引编号

         * @return 返回指定索引节点包含的数据

         */

        public Book getNode(int index) {

            // 使用当前的foot内容与要查询的索引进行比较,随后将foot的内容自增,目的是下次查询方便

            if (Link.this.foot++ == index) { // 当前为要查询的索引

               return this.data; // 返回当前节点数据

            } else { // 继续向后查询

               return this.next.getNode(index); // 进行下一个节点的判断

            }

        }

        /**

         * 修改指定索引节点包含的数据

         * @param index 要修改的索引编号

         * @param data 新数据

         */

        public void setNode(int index, Book data) {

        // 使用当前的foot内容与要查询的索引进行比较随后将foot的内容自增目的是下次查询方便

            if (Link.this.foot++ == index) { // 当前为要修改的索引

               this.data = data; // 进行内容的修改

            } else {

               this.next.setNode(index, data); // 继续下一个节点的索引判断

            }

        }

        /**

         * 节点的删除操作,匹配每一个节点的数据,如果当前节点数据符合删除数据

         * 则使用当前节点上一节点.next = 当前节点.next方式空出当前节点

         * 第一次调用(Link)previous = Link.root、this = Link.root.next

         * 第二次调用(Node)previous = Link.root.next、this = Link.root.next.next

         * @param previous 当前节点的上一个节点

         * @param data 要删除的数据

         */

        public void removeNode(Node previous, Book data) {

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

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

            } else { // 应该向后继续查询

               this.next.removeNode(this, data); // 继续下一个判断

            }

        }

        /**

         * 将节点中保存的内容转化为对象数组

         * 第一次调用(Link):this = Link.root;

         * 第二次调用(Node):this = Link.root.next;

         */

        public void toArrayNode() {

            Link.this.retArray[Link.this.foot++] = this.data; // 取出数据并保存在数组中

            if (this.next != null) { // 有后续元素

               this.next.toArrayNode(); // 继续下一个数据的取得

            }

        }

    }

    // ===================== 以上为内部类 ===================

    private Node root; // 根节点定义

    private int count = 0 ; // 保存元素的个数

    private int foot = 0 ; // 节点索引

    private Book [] retArray ; // 返回的数组

    /**

     * 用户向链表增加新的数据,在增加时要将数据封装为Node类,这样才可以匹配节点顺序

     * @param data 要保存的数据

     */

    public void add(Book data) { // 假设不允许有null

        if (data == null) { // 判断数据是否为空

           return; // 结束方法调用

        }

        Node newNode = new Node(data); // 要保存的数据

        if (this.root == null) { // 当前没有根节点

           this.root = newNode; // 保存根节点

        } else { // 根节点存在

            this.root.addNode(newNode); // 交给Node类处理节点的保存

        }

        this.count ++ ; // 数据保存成功后保存个数加一

    }

    /**

     * 取得链表中保存的数据个数

     * @return 保存的个数,通过count属性取得

     */

    public int size() { // 取得保存的数据量

        return this.count;

    }

    /**

     * 判断是否是空链表,表示长度为0,不是null

     * @return 如果链表中没有保存任何数据则返回true,否则返回false

     */

    public boolean isEmpty() {

        return this.count == 0;

    }

    /**

     * 数据查询操作,判断指定数据是否存在,如果链表没有数据直接返回false

     * @param data 要判断的数据

     * @return 数据存在返回true,否则返回false

     */

    public boolean contains(Book data) {

        if (data == null || this.root == null) { // 现在没有要查询的数据,根节点也不保存数据

           return false ; // 没有查询结果

        }

        return this.root.containsNode(data) ; // 交由Node类查询

    }

    /**

     * 根据索引取得保存的节点数据

     * @param index 索引数据

     * @return 如果要取得的索引内容不存在或者大于保存个数返回null,反之返回数据

     */

    public Book get(int index) {

        if (index > this.count) { // 超过了查询范围

           return null ; // 没有数据

        }

        this.foot = 0 ; // 表示从前向后查询

        return this.root.getNode(index) ; // 查询过程交给Node

    }

    /**

     * 根据索引修改数据

     * @param index 要修改数据的索引编号

     * @param data 新的数据内容

     */

    public void set(int index, Book data) {

        if (index > this.count) { // 判断是否超过了保存范围

           return; // 结束方法调用

        }

        this.foot = 0; // 重新设置foot属性的内容,作为索引出现

        this.root.setNode(index, data); // 交给Node类设置数据内容

    }

    /**

     * 链表数据的删除操作,在删除前要先使用contains()判断链表中是否存在指定数据

     * 如果要删除的数据存在则首先判断根节点的数据是否为要删除数据

     * 如果是则将根节点的下一个节点作为新的根节点

     * 如果要删除的数据不是根节点数据,则将删除操作交由Node类的removeNode()方法完成

     * @param data 要删除的数据

     */

    public void remove(Book data) {

        if (this.contains(data)) { // 主要功能是判断数据是否存在

            // 要删除数据是否是根节点数据,root是Node类的对象,此处直接访问内部类的私有操作

            if (data.equals(this.root.data)) { // 根节点数据为要删除数据

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

            } else { // 根节点数据不是要删除数据

               // 此时根元素已经判断过了,从第二个元素开始判断,即第二个元素的上一个元素为根节点

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

            }

            this.count--; // 删除成功后个数要减少

        }

    }

    /**

     * 将链表中的数据转换为对象数组输出

     * @return 如果链表没有数据返回null,如果有数据则将数据变为对象数组后返回

     */

    public Book[] toArray() {

        if (this.root == null) { // 判断链表是否有数据

           return null; // 没有数据返回null

        }

        this.foot = 0; // 脚标清零操作

        this.retArray = new Book[this.count]; // 根据保存内容开辟数组

        this.root.toArrayNode(); // 交给Node类处理

        return this.retArray; // 返回数组对象

    }

    public void clear() {

        this.root = null; // 清空链表

        this.count = 0; // 元素个数为0

    }

}

范例1-135:实现测试。

public class LinkDemo {

    public static void main(String args[]) {

        Link all = new Link(); // 创建链表对象

        all.add(new Book("Java开发实战经典",79.8)); // 保存数据

        all.add(new Book("Oracle开发实战经典",89.8)); // 保存数据

        all.add(new Book("Android开发实战经典",99.8)); // 保存数据

        System.out.println("保存书的个数:" + all.size()) ;

        System.out.println(all.contains(new Book("Java开发实战经典",79.8))) ;

        all.remove(new Book("Android开发实战经典",99.8)) ;

        Book [] books = all.toArray() ;

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

            System.out.println(books[x].getInfo()) ;

        }

    }

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值