技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> Java --> [Java基础教程]第十一章-Java类和对象

[Java基础教程]第十一章-Java类和对象

浏览:2110次  出处信息

继承是面向对象的三个特性之一,Java语言通过继承父类和实现接口两种方式实现继承。Java的继承有两个比较重要的特点:单继承结构,每个类只能有一个父类;所有的类继承java.lang .Object类。Object类中包含了多个默认实现的方法,其中常用的有3个,hashCode,equals,toString:
hashCode:返回对象的哈希码,我们前面学习的HashSet和HashMap容器在put和get时会调用这个方法,默认实现是返回对象在内存上的地址。
equals:对象比较,默认比较对象的地址,所以两个对象之间使用默认equals是不相等的。通常应用中会重写equals方法,使用对象的关键属性做为对象的比较,比如Person对象我们应该比较该对象的身份证号,如果身份证号码一致则是同一个人。Java规范要求:根据 equals(Object) 方法,两个对象是相等的,那么在两个对象中的每个对象上调用 hashCode 方法都必须生成相同的整数结果。所以我们在重写equals的时候同时也会重写hashCode方法。
toString:正是因为这个方法的存在,我们才能对所有的对象进行打印。默认的toString实现为:类全名(包括包结构)@hashCode,我们通常会重写该方法为输出所有属性值拼接的字符串。
备注:子类中重新实现父类的方法就是重写。

我们接着前面一章的打酱油继续看,其中有一个人物我们没有处理,小明的妈妈,会做菜的家庭主妇,所以我们需要定义一个类Materfamilias它具有Person的所有属性和方法,并且具有cook的方法,会cook的还可能会是厨师,所以我们可以把cook抽象成一个接口类Cookor,结构如下:

对象继承结构

接口的定义使用Interface关键字,继承类和实现类分别为extends和implements,java是单继承和多实现的方式,也就是说类可以实现多个接口,代码如下:

public interface Cookor {
    public void cook();
}  
public class Materfamilias extends Person implements Cookor {
    /**
     * @param name
     */
    public Materfamilias(String name) {
        super(name);
    }
    /* (non-Javadoc)
     * @see com.sunhaojie.learntest.eleventh.Cookor#cook()
     */
    @Override
    public void cook() {
        System.out.println(this.getName() + "煮了一顿饭");
    }
}

接口中的方法不能带有”{}”的实现。

在前面几章中我们定义类的属性和方法前面会加一个单词修饰,比如private,public等,这些是对属性和方法访问权限的定义。这些修饰符共4个分别为,private,protected,default(没有修饰符),public。4种修饰符对应的访问权限如下表:


当前类子类同一个包类其他类
privateYNNN
protectedYYNN
defaultY同包?Y:NYN
publicYYYY

当前类:当前类中的方法
子类:继承当前类的子类
同一个包类:在同一个package下的类
其他类:以上3中以外的类

类的类,有点拗口,面向对象的思想,一切都是对象,那么类的定义也是对象,也有类描述-Class类,类的属性,类的方法等都是有类定义,通过这种方式访问类和对象的方式叫做反射。我们通过反射生成对象,获取属性,调用方法,代码如下:

public static void main(String[] args) throws ClassNotFoundException, InstantiationException,
        IllegalAccessException, NoSuchFieldException, SecurityException, NoSuchMethodException,
        IllegalArgumentException, InvocationTargetException {
    Class<Materfamilias> materfamiliasClass = (Class<Materfamilias>) Class
            .forName("com.sunhaojie.learntest.eleventh.Materfamilias");
    // 初始化对象,并调用cook方法
    Materfamilias mama = materfamiliasClass.newInstance();
    mama.cook();
    // 获取父类name属性,并打印结果值
    Field field = materfamiliasClass.getSuperclass().getDeclaredField("name");
    field.setAccessible(true);
    String mamaName = (String) field.get(mama);
    System.out.println("mama.getName():" + mama.getName() + "; field get name:" + mamaName);
      
    // 调用无参方法cook
    Method cookMethod = materfamiliasClass.getDeclaredMethod("cook");
    cookMethod.invoke(mama);
    // 调用父类有参方法
    Method setNameMethod = materfamiliasClass.getSuperclass().getDeclaredMethod("setName", String.class);
    setNameMethod.invoke(mama, "xiao ming mama");
    System.out.println(mama.getName());
}

我们在上面的代码中实现了初始化对象(这里需要一个无参的构造方法),获取属性值,调用有参和无参的方法。反射这种方式应用程序开发使用比较少,但是一些框架经常使用,所以我们这里做一个简单了解。

我们在前面的测试中会直接运行main方法,main方法前面有一个关键字static,这个关键字可以在属性和方法前,表示类属性和类方法,也就是不用初始化对象就可以调用,显然这个语法和面向对象思想相悖,但是某些场景下也会用到。

和Interface比较类似,有一种类的方法也不用实习,抽象类abstract,因为java是单继承结构,所以我们尽量使用Interface接口尽量少使用abstract抽象类。

枚举enum,这种类在定义明确种类,状态时经常使用,比如酱油,可以分为瓶装,袋装和无包装3种,我们就可以定义一个枚举类实现这种方式,使用枚举的优势是运行效率高。酱油类别枚举:

public enum SoyType {
    BOTTLED("瓶装"), BAG("袋装"), NOWRAP("无包装");
    public String name;
      
    /**
     * 如果不需要属性,就可以不用定义构造方法
     * 
     * @param name
     */
    private SoyType(String name) {
        this.name = name;
    }
}

小练习:
打印Materfamilias类的属性和方法名称,以及父类和接口的属性和方法。

课程中的代码:

package com.sunhaojie.learntest.eleventh;
/**
 * @ClassName Cookor
 * @Description 烹饪功能接口
 *
 * @author sunhaojie 3113751575@qq.com
 * @date 2016年2月11日 上午12:05:28
 */
public interface Cookor {
    public void cook();
}
package com.sunhaojie.learntest.eleventh;
  
import java.util.HashSet;
import java.util.Set;
  
import com.sunhaojie.learntest.tenth.Soy;
  
/**
 * @ClassName Person
 * @Description 人
 *
 * @author sunhaojie 3113751575@qq.com
 * @date 2016年2月3日 下午1:38:30
 */
public class Person {
    /**
     * 名字
     */
    private String name;
    /**
     * 酱油列表
     */
    private Set<Soy> soyList;
  
    /**
     * 
     * @Title buy
     * @Description 买酱油
     * @param soy
     * @return void
     *
     * @author sunhaojie 3113751575@qq.com
     * @date 2016年2月3日 下午4:59:31
     */
    public void buy(Soy soy) {
        if (soyList == null) {
            this.soyList = new HashSet<Soy>();
        }
  
        this.soyList.add(soy);
    }
  
    /**
     * @param name
     */
    public Person(String name) {
        this.name = name;
    }
  
    public String getName() {
        return name;
    }
  
    public void setName(String name) {
        this.name = name;
    }
  
    public Set<Soy> getSoyList() {
        return soyList;
    }
  
    public void setSoyList(Set<Soy> soyList) {
        this.soyList = soyList;
    }
  
}
package com.sunhaojie.learntest.eleventh;
/**
 * @ClassName Materfamilias
 * @Description 家庭主妇
 *
 * @author sunhaojie 3113751575@qq.com
 * @date 2016年2月10日 下午11:04:16
 */
public class Materfamilias extends Person implements Cookor {
    /**
     * 无参构造方法
     */
    public Materfamilias() {
        super("mama");
    }
    /**
     * @param name
     */
    public Materfamilias(String name) {
        super(name);
    }
    /* (non-Javadoc)
     * @see com.sunhaojie.learntest.eleventh.Cookor#cook()
     */
    @Override
    public void cook() {
        System.out.println(this.getName() + "煮了一顿饭");
    }
}
package com.sunhaojie.learntest.eleventh;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
 * @ClassName ClassTest
 * @Description 反射测试类
 *
 * @author sunhaojie 3113751575@qq.com
 * @date 2016年2月11日 下午10:31:58
 */
public class ClassTest {
    /**
     * @Title main
     * @Description main方法
     * @param args
     * @return void
     *
     * @author sunhaojie 3113751575@qq.com
     * @throws ClassNotFoundException
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws SecurityException
     * @throws NoSuchFieldException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws IllegalArgumentException
     * @date 2016年2月11日 下午10:31:58
     */
    @SuppressWarnings("unchecked")
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException,
            IllegalAccessException, NoSuchFieldException, SecurityException, NoSuchMethodException,
            IllegalArgumentException, InvocationTargetException {
        Class<Materfamilias> materfamiliasClass = (Class<Materfamilias>) Class
                .forName("com.sunhaojie.learntest.eleventh.Materfamilias");
        // 初始化对象,并调用cook方法
        Materfamilias mama = materfamiliasClass.newInstance();
        mama.cook();
        // 获取父类name属性,并打印结果值
        Field field = materfamiliasClass.getSuperclass().getDeclaredField("name");
        field.setAccessible(true);
        String mamaName = (String) field.get(mama);
        System.out.println("mama.getName():" + mama.getName() + "; field get name:" + mamaName);
          
        // 调用无参方法cook
        Method cookMethod = materfamiliasClass.getDeclaredMethod("cook");
        cookMethod.invoke(mama);
        // 调用父类有参方法
        Method setNameMethod = materfamiliasClass.getSuperclass().getDeclaredMethod("setName", String.class);
        setNameMethod.invoke(mama, "xiao ming mama");
        System.out.println(mama.getName());
    }
}
package com.sunhaojie.learntest.eleventh;
/**
 * @ClassName SoyType
 * @Description 酱油种类
 *
 * @author sunhaojie 3113751575@qq.com
 * @date 2016年2月11日 下午11:21:00
 */
public enum SoyType {
    BOTTLED("瓶装"), BAG("袋装"), NOWRAP("无包装");
    public String name;
      
    /**
     * 如果不需要属性,就可以不用定义构造方法
     * 
     * @param name
     */
    private SoyType(String name) {
        this.name = name;
    }
}

建议继续学习:

  1. 面向对象的Shell脚本    (阅读:5160)
  2. 用星际争霸讲解面向对象的概念    (阅读:4157)
  3. 使用PHP创建一个面向对象的博客    (阅读:4078)
  4. PHP面向对象编程的三大特性    (阅读:3361)
  5. 面向对象设计模式的核心法则    (阅读:3178)
  6. PHP内核介绍及扩展开发指南―类和对象    (阅读:2989)
  7. 对象的消息模型    (阅读:2512)
  8. jQuery之jQuery方法总是返回jQuery对象    (阅读:2369)
  9. 我所偏爱的 C 语言面向对象编程范式    (阅读:2077)
  10. 细说JavaScript中对象的属性和方法    (阅读:2062)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1