类中可以包含属性,也被称为类的成员变量,是相对于方法中的局部变量而言的。
其中属性的数据类型可以是Java的基本数据类型和引用数据类型两种。
下面的类SprinklerSystem 展示了两种数据类型的属性,分别是基本数据类型(int i,double)和引用数据类型的自定义类WaterSource。来自于Java编程思想第四版-复用类
package tony.javacore.object.composition;
import static tony.javacore.util.io.IOUtils.println;
/** * 对象的组合使用 * @author tony [email protected] * @file SprinklerSystem.java * @version 2016年2月6日下午6:26:18 * @since JDK7u80 */
public class SprinklerSystem { // 洒水车系统
private String valve1, valve2, valve3, valve4;
/* 实例化WaterSource对象在创建SprinklerSystem对象执行 */
private WaterSource waterSource = new WaterSource();
/* 基本数据类型 */
private int i;
private double d;
{
i = 87; // 代码的等价效果 private int i=47;
}
@Override
public String toString() {
return "SprinklerSystem [valve1=" + valve1 + ", valve2=" + valve2 + ", valve3=" + valve3 + ", valve4=" + valve4
+ ", waterSource=" + waterSource + ", i=" + i + ", d=" + d + "]";
}
public static void main(String[] args) {
SprinklerSystem sprinklerSystem = new SprinklerSystem();
println(sprinklerSystem); // toString方法可以让任意的对象以字符串的形式输出
}
}
class WaterSource {
private String s;
WaterSource() {
println("WaterSource()");
s = "Constructed";
}
@Override
public String toString() {
return s;
}
}
当一个类(SprinklerSystem )持有另一个类的引用(WaterSource waterSource)时,就使用了对象的组合。在日常开发中经常会使用这种组合的对象实现对应的功能,例如JavaEE企业级的分成开发中通常会采用分层开发的方式(MVC模式),Service层都会持有一个DAO(数据访问层)的引用用于完成数据访问的功能。
类中可以定义若干个方法,用于完成对象或者类对应的业务逻辑。
package tony.javacore.object.method;
import static tony.javacore.util.io.IOUtils.println;
public class Storage {
/* static修饰的变量属于类变量,不属于对象 */
static String content = "Hello World";
/** * 定义带返回值(int)的方法 * * @param ref * @return */
int storage(String ref) {
return content.length() * 2;
}
/** * 定义不带返回值的方法 */
void print() {
println("storage(storage(ref))" + storage(content));
}
public static void main(String[] args) {
// 实例化对象
Storage s = new Storage();
// 调用对象的方法
s.storage(content);
s.print();
}
}
重载:同一个类中包含了两个或以上的方法名相同,方法的参数列表不同,则成为方法重载(Overload)
package tony.javacore.object.method.overload;
import static tony.javacore.util.io.IOUtils.println;
/** * 方法重载 * @author tony [email protected] * @file OverloadDog.java * @version 2016年2月6日下午6:30:08 * @since JDK7u80 */
public class OverloadDog {
public static void main(String[] args) {
Dog dog =new Dog();
/*调用重载的方法*/
dog.bark();
dog.bark(1);
dog.bark(1.1);
}
}
class Dog{
public void bark(){
println("Dog.bark()");
}
public void bark(int i){
println("Dog.bark("+i+")");
}
public void bark(double d){
println("Dog.bark("+d+")");
}
}
方法的参数顺序不同也是重载
package tony.javacore.object.method.overload;
import static tony.javacore.util.io.IOUtils.println;
/** * 重载时,方法的参数顺序不同也是重载 * @author tony [email protected] * @file OverloadingOrder.java * @version 2016年2月6日下午6:31:20 * @since JDK7u80 */
public class OverloadingOrder {
static void showArgOrder(String str,int i){
println("String : "+str+ " int :"+ i);
}
static void showArgOrder(int i,String str){
println("int :"+ i + " String :"+str);
}
public static void main(String[] args) {
showArgOrder(11, "Int First");
showArgOrder("String First", 99);
}
}
方法的重写:当子类继承类父类,并包含与父类同名方法的现象被称为方法重写(Override),也被称为方法覆盖。可以说子类重写了父类的方法,也可以说子类覆盖了父类的方法。
方法重写时,需要遵循方法名相同,参数列表相同,子类方法的返回类型比父类的要小,子类方法声明抛出的异常类比父类更小或者相等。
Product类分别重写了父类Product的toString()和description()方法
package tony.javacore.object.method.overload;
import static tony.javacore.util.io.IOUtils.println;
import tony.javacore.object.oop.bean.Memory;
import tony.javacore.object.oop.bean.Product;
/** * 重写父类的方法 * @author tony [email protected] * @file Computer.java * @version 2016年2月6日下午6:35:17 * @since JDK7u80 */
public class Computer extends Product {
private Memory memory =new Memory(12);
@Override
public void description() {
println("I'm a computer, memory size is "+memory.getCapacity());
}
@Override
public String toString() {
return "I'am Computer";
}
public static void main(String[] args) {
Product product =new Computer();
product.description();
println(product);
}
}
Java方法的参数传递机制:传递值(value),就是将实际参数的副本传入方法内,而参数本身不会受任何影响。但是引用数据类型作为参数传递时传递的是对象的地址值,在方法中修改引用地址指向的那个对象。引用地址没有改变,但是对象的内容(成员变量的值)是改变了。
package tony.javacore.object.method;
import static tony.javacore.util.io.IOUtils.println;
/** * Java方法参数传递机制 * @author tony [email protected] * @file MethodArgPassHandler.java * @version 2016年2月6日下午6:37:16 * @since JDK7u80 */
public class MethodArgPassHandler {
public static void main(String[] args) {
int num1 =8;
int num2 =9;
println("swap方法调用之前: num1 ="+num1 +" num2 ="+num2);
PrimitveType.swap(num1,num2);
println("swap方法调用之后:num1 ="+num1 +" num2 ="+num2);
ReferenceType type =new ReferenceType(num1,num2);
println("swap方法调用之前:"+type);
ReferenceType.swap(type);
println("swap方法调用之后:"+type);
}
}
class PrimitveType {
/** * 两个变量值交换 * * @param num1 * @param num2 */
static void swap(int num1, int num2) {
// 定义临时变量存储num1的值
int tmp = num1;
num1 = num2;
num2 = tmp;
println("swap方法中: num1 =" + num1 + " num2 =" + num2);
}
}
class ReferenceType{
private int num1;
private int num2;
public int getNum1() {
return num1;
}
public void setNum1(int num1) {
this.num1 = num1;
}
public int getNum2() {
return num2;
}
public void setNum2(int num2) {
this.num2 = num2;
}
public ReferenceType(int num1,int num2) {
this.num1=num1;
this.num2=num2;
}
@Override
public String toString() {
return "ReferenceType [num1=" + num1 + ", num2=" + num2 + "]";
}
/** * 交换引用类型成员变量的值 * @param type */
public static void swap(ReferenceType type){
int tmp =type.getNum1();
type.setNum1(type.getNum2());
type.setNum2(tmp);
println("swap方法中:"+type);
}
}
可变参数列表是JDK5.0提供的新特性,如果在某一个类型后跟省略号,则可以表示该参数可以是任意个数的同类型变量(0-n之间)。此时与Object[]数组不同的是,它的参数不是一个,而是可以变化的。显然这种方式更加人性化。
事实上底层维护的就是一个数组,只是长度在运行期才确定
package tony.javacore.object.method.overload;
import static tony.javacore.util.io.IOUtils.println;
/** * 重载的可变参数 * * @author tony [email protected] * @file OverloadingVarArgs.java * @version 2016年2月6日下午6:38:51 * @since JDK7u80 */
public class OverloadingVarArgs {
public static void printArray(Object... args) {
println("execute method printArray(Object ...args)");
for (Object obj : args) {
println(obj);
}
}
public static void printArray(int required, Object... args) {
println("execute method printArray(int required,Object...args)");
}
public static void main(String[] args) {
printArray(new Object[] { 1, 2, "3", '4', 5.0, 5.0f, false });
printArray();// 不传递参数也是OK的
printArray(1, new Object[] { "content", 12 });
}
}
如果使用了可变参数的重载,必须要添加一个非可变参数。