上季内容回顾:
题目的分析和类图的设计
本季主要知识点:
本季要点:内部类的定义、使用和外部调用。
本季重点讲解了JAVA中的内部类和对象数组的使用,以及对上季中的习题进一步引申。
[零基础学JAVA]Java SE面向对象部分-11.面向对象基础(06)_内部类
上季内容遗留下来这么一道题目,我们来分析一下哈~
class Employee    
{
  private String empno ;
  private String empname ;
  private float salary ;
  private float inc ;

  //构造方法
  public Employee(){}
  public Employee(String empno,String empname,float salary,float inc){
    this.setEmpno(empno);
    this.setEmpname(empname);
    this.setSalary(salary);
    this.setInc(inc);
  }

  //setter和getter
  public void setEmpno(String empno){
         this.empno = empno ;
  }
  public void setEmpname(String empname){
         this.empname = empname ;
  }
  public void setSalary(float salary){
         this.salary = salary ;
  }
  public void setInc(float inc){
         this.inc = inc ;
  }
  public String getEmpno(){
         return this.empno ;
  }
  public String getEmpname(){
         return this.empname ;
  }
  public float getSalary(){
         return this.salary ;
  }
  public float getInc(){
         return this.inc ;
  }
    
  //计算增长后的工资总额
  public float calSalary(){
    return this.salary+this.salary*this.inc;
  }
}
public class Demo01
{
  public static void main(String args[]){
    Employee e = new Employee("e001","王乾",5000.0f,0.1f);
    System.out.println(e.calSalary());
  }
}
测试下哈~
[零基础学JAVA]Java SE面向对象部分-11.面向对象基础(06)_面向对象_02
[零基础学JAVA]Java SE面向对象部分-11.面向对象基础(06)_面向对象_03
class Math
{
  private float x;
  private float y;

  public Math(){}
  public Math(float x,float y){
    this.setX(x);
    this.setY(y);
  }

  //求和
  public float sum(){
    return this.x + this.y;
  }
  //求差
  public float sub(){
    return this.x - this.y;
  }
  //求平均值
  public float avg(){
    return this.sum() / 2;
  }
  //求最大值
  public float max(){
    return this.x>this.y?this.x:this.y;
  }
  //求最小值
  public float min(){
    return this.x<this.y?this.x:this.y;
  }

  public void setX(float x){
    this.x = x;
  }
  public void setY(float y){
    this.y = y;
  }
  public float getx(){
    return this.x;
  }
  public float gety(){
    return this.y;
  }
}
public class Demo02
{
  public static void main(String args[]){
  Math m = new Math(50.0f,60.0f);
  System.out.println("求和:"+m.sum());
  System.out.println("求差:"+m.sub());
  System.out.println("平均值:"+m.avg());
  System.out.println("最大值:"+m.max());
  System.out.println("最小值:"+m.min());
  }
}
我们验证下计算结果对不对哈~
[零基础学JAVA]Java SE面向对象部分-11.面向对象基础(06)_构造方法_04
内部类
[零基础学JAVA]Java SE面向对象部分-11.面向对象基础(06)_面向对象_05
本次专题中JAVA SE 课程已经融合了JAVA EE的设计思路
在一个类的内部还有另外一个类
class Outer{    
        定义了若干个属性    
        定义了若干个方法    
        class Inner{    
        // 内部类    
        }    
}
内部类定义后有什么好处呢?我们来看Demo03哈~
//外部类
class Outer
{
  private String name = "redking.blog.51cto.com" ;
  //内部类
  class Inner
  {
    //此方法用于打印Outer类中的name属性
    public void printName(){
      System.out.println("name = "+name) ;
    }
  }
  //定义一个外部类的方法
  public void fun(){
    //产生内部类的实例化对象,同时调用里面的方法
    new Inner().printName() ;
  }
}
public class Demo03
{
  public static void main(String args[]){
  //产生了外部类的对象
  Outer out = new Outer() ;
  //调用fun()方法之后打印输出
  out.fun() ;
  }
}
验证下效果
[零基础学JAVA]Java SE面向对象部分-11.面向对象基础(06)_面向对象_06
编译*.java文件之后,可以发现产生了两个文件:
· Outer$Inner.class : Outer.Inner,如果要想找到Inner类,则必须先找到Outer
· Outer.class :外部类的class文件。
能否发现内部类有哪些好处呢?
现在将内部类拿到外部类之外,要求;最后可以实现同样的程序,我们来看Demo04哈~
//外部类
class Outer
{
  private String name = "redking.blog.51cto.com" ;
  //定义一个外部类的方法
  public void fun(){
    //产生内部类的实例化对象,同时调用里面的方法
    new Inner(this).printName() ;
  }
  //必须使用setter和getter方法
  public void setName(String name){
    this.name = name ;
  }
  public String getName(){
    return this.name ;
  }
}
//现在我们把内部类拿到外部,这样就形成了两个类哈~
//内部类
class Inner
{
  //必须想办法为out对象实例化
  private Outer out = null ;
  public Inner(Outer out){
    this.out = out ;
  }
  //此方法用于打印Outer类中的name属性
  public void printName(){
    //此处如果要访问name属性,则肯定必须通过Outer类的对象来完成
    System.out.println("name = "+out.getName()) ;
  }
}
public class Demo04
{
  public static void main(String args[]){
  //产生了外部类的对象
  Outer out = new Outer() ;
  //调用fun()方法之后打印输出
  out.fun() ;
  }
}
修改完后我们看下效果
[零基础学JAVA]Java SE面向对象部分-11.面向对象基础(06)_内部类_07
以上程序多了很多内容:
1、 Outer.class类中多了setter和getter方法,同时在fun方法中还必须传入当前操作Outer类的对象,因为Inner类中必须使用此对象才可以访问Outer类中的属性。
2、 Inner.class 类中多了一个构造方法,用于接收Outer 类的实例化对象,同时必须使用对象.方法()的形式才可以找到name的值并输出。
综合以上几点,发现内部类的优缺点
· 内部类访问外部类的私有属性很方便
· 内部类在使用时代码的结构是不好的
下面我们还是看Demo03,在此基础上我们不想使用fun()方法调用printName()方法,希望直接在主方法中调用,我们看下面。
//外部类
class Outer
{
  private String name = "redking.blog.51cto.com" ;
  //内部类
  class Inner
  {
    //此方法用于打印Outer类中的name属性
    public void printName(){
      System.out.println("name = "+name) ;
    }
  }
}
public class Demo05
{
  public static void main(String args[]){
  //产生了外部类的对象
  Outer out = new Outer() ;
  //能否直接在Main方法中直接产生Inner类的实例化对象
  //调用printName方法呢?我们验证一下哈~~~
  //声明内部类对象:外部类.内部类 内部类对象 = null ;
  //实例化内部类对象:内部类对象 = new 外部类实例.new 内部类() :
  Outer.Inner in = out.new Inner() ;
  in.printName() ;
  }
}
测试下,可以哈,这是这样代码就更加别扭了哈~
[零基础学JAVA]Java SE面向对象部分-11.面向对象基础(06)_零基础学JAVA_08
此外,也可以在一个方法中定义内部类。
class Outer
{
  private String name = "redking.blog.51cto.com" ;
  public void fun(){
    //在方法中定义内部类
    class Inner
    {
      public void print(){
        System.out.println("name = "+name);
      }
    }
    new Inner().print();
  }
}
public class Demo06
{
  public static void main(String args[]){
    new Outer().fun();
  }
}
验证下
[零基础学JAVA]Java SE面向对象部分-11.面向对象基础(06)_内部类_09
注意点:
在方法中定义的内部类,可以访问外部类的任何属性,但是不能直接访问方法中的参数或变量。
这么理解呢?我们来看下Demo07哈~
class Outer
{
  private String name = "redking.blog.51cto.com" ;
  public void fun(int i){
    int j = 10 ;
    //在方法中定义内部类
    class Inner
    {
      public void print(){
        System.out.println("name = "+name);
        System.out.println("i+j = "+(i+j));
      }
    }
    new Inner().print();
  }
}
public class Demo07
{
  public static void main(String args[]){
    new Outer().fun(20);
  }
}
就像这样哈:
[零基础学JAVA]Java SE面向对象部分-11.面向对象基础(06)_JAVA_10
如果想在内部类中访问方法中的参数,则参数前必须加上一个“final”关键字。
class Outer
{
  private String name = "redking.blog.51cto.com" ;
  public void fun(final int i){
    final int j = 10 ;
    //在方法中定义内部类
    class Inner
    {
      public void print(){
        System.out.println("name = "+name);
        System.out.println("i+j = "+(i+j));
      }
    }
    new Inner().print();
  }
}
public class Demo08
{
  public static void main(String args[]){
    new Outer().fun(20);
  }
}
现在程序就执行了
[零基础学JAVA]Java SE面向对象部分-11.面向对象基础(06)_JAVA_11
对象数组:
· 数组:是一组相同类型变量的集合
· 对象数组:就是一组对象。
对象数组的定义格式:
声明对象数组:类名称 [] 对象数组名称 = null ;
为对象数组开辟空间:对象数组名称 = new 类名称[个数] ;
注意:
数组中使用new开辟空间之后,所有的数据都是默认值,对象的默认值就是null。
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 Demo09
{
  public static void main(String arg[]){
    //声明一个Person类的对象数组
    Person p[] = null ;
    //为对象数组开辟空间
    p = new Person[10] ;
    //开辟空间之后所有的内容都是默认值,引用的为null
    for (int i=0;i<p.length ;i++ )
    {
      System.out.println(p[i]);
    }
  }
};
我们看下效果,现在所有的对象的默认值都是null
[零基础学JAVA]Java SE面向对象部分-11.面向对象基础(06)_JAVA_12
现在我们分别为对象数组中的每个元素实例化
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 Demo10
{
  public static void main(String arg[]){
    //声明一个Person类的对象数组
    Person p[] = null ;
    //为对象数组开辟空间
    p = new Person[10] ;
    //因为使用的是动态初始化
    //所以此处必须依次为其实例化,对象数组中的每一个元素都是null
    for (int i=0;i<p.length ;i++ )
    {
      //分别为对象数组中的每个元素实例化
      p[i] = new Person("michael"+i,20+i);
    }
    //开辟空间之后所有的内容都是默认值,引用的为null
    for (int i=0;i<p.length ;i++ )
    {
      System.out.println(p[i]);
    }
  }
};
我们看下对象数组中有没内容了
[零基础学JAVA]Java SE面向对象部分-11.面向对象基础(06)_构造方法_13
对象数组中每个元素都有内容了,下面我们就来取出内容哈~
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 Demo11
{
  public static void main(String arg[]){
    //声明一个Person类的对象数组
    Person p[] = null ;
    //为对象数组开辟空间
    p = new Person[10] ;
    //因为使用的是动态初始化
    //所以此处必须依次为其实例化,对象数组中的每一个元素都是null
    for (int i=0;i<p.length ;i++ )
    {
      //分别为对象数组中的每个元素实例化
      p[i] = new Person("michael"+i,20+i);
    }
    //开辟空间之后所有的内容都是默认值,引用的为null
    for (int i=0;i<p.length ;i++ )
    {
      System.out.println(p[i].getInfo());
    }
  }
};
验证下
[零基础学JAVA]Java SE面向对象部分-11.面向对象基础(06)_构造方法_14
这就叫对象数组哈~
对象数组也可以采用静态初始化方式:
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 Demo12
{
  public static void main(String arg[]){
    //声明一个Person类的对象数组
    Person p[] = {new Person("michael",30),new Person("amy",31),new Person("joy",32)} ;
    //开辟空间之后所有的内容都是默认值,引用的为null
    for (int i=0;i<p.length ;i++ )
    {
      System.out.println(p[i].getInfo());
    }
  }
};
看下效果哈~
[零基础学JAVA]Java SE面向对象部分-11.面向对象基础(06)_构造方法_15
思考题:
建立一个Student 类,里面包含name、age、score 属性,现在要求生成十个Student 对象,之后对这些对象进行排序,按成绩由高到低排序,如果成绩相等,则按年龄由高到低排序。

总结
1、内部类的使用
· 内部类的优点与缺点
2、对象数组,是一组对象,必须分别实例化
3、思考题非常重要哈~~~(留到面向对象结束后分析哈)
###############################################################