8

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

 3 years ago
source link: https://blogread.cn/it/article/7898?f=hot1
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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

浏览:1130次  出处信息

继承是面向对象的三个特性之一,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种修饰符对应的访问权限如下表:

当前类子类同一个包类其他类privateYNNNprotectedYYNNdefaultY同包?Y:NYNpublicYYYY

当前类:当前类中的方法
子类:继承当前类的子类
同一个包类:在同一个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 [email protected]
* @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 [email protected]
* @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 [email protected]
* @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 [email protected]
* @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 [email protected]
* @date 2016年2月11日 下午10:31:58
*/
public class ClassTest {
/**
* @Title main
* @Description main方法
* @param args
* @return void
*
* @author sunhaojie [email protected]
* @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 [email protected]
* @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;
}
}

觉得文章有用?立即:

和朋友一起 共学习 共进步!

建议继续学习:

QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK