一、封装 (encapsulation)
定义:封装就是将客户端不应看到的信息包裹起来。使内部执行对外部来看不一种不透明的、是一个黑箱,客户端不需要内部资源就能达到他的目的。
1.事物的内部实现细节隐藏起来
2.对外提供一致的公共的接口――间接访问隐藏数据
3.可维护性
对类成员访问的限制及子类继承情况: (从严 到宽 )
private 私有,本类内部 不能继承
(default) 本类+同包 同包子类可继承
protected 本类+同包+子类 可以继承
public 公开 任何地方都可以访问 能继承到子类
class Parent
{
public void nonStaticMethod()
{
System.out.println("Parent's Non-Static Method is Called");
}
public static void staticMethod()
{
System.out.println("parent's static method is called");
}
}
class Child extends Parent
{
public void nonStaticMethod()
{
System.out.println("child's non-static method is called");
}
public static void staticMethod()
{
System.out.println("child's static method is called");
}
}
public class Test
{
public static void main(String args[])
{
Parent p1 = new Parent();
Parent p2 = new Child();
Child c = new Child();
System.out.print("Parent.static: "); Parent.staticMethod();
System.out.print("p1.static: "); p1.staticMethod();
System.out.print("p2.static: "); p2.staticMethod();
System.out.print("p1.nonStatic: "); p1.nonStaticMethod();
System.out.print("p2.nonStatic: "); p2.nonStaticMethod();
System.out.print("Child.static: "); Child.staticMethod();
System.out.print("c.static: "); c.staticMethod();
System.out.print("c.nonStatic: "); c.nonStaticMethod();
}
}
程序的运行结果为:
Parent.static: parent's static method is called
p1.static: parent's static method is called
p2.static: parent's static method is called
p1.nonStatic: Parent's Non-Static Method is Called
p2.nonStatic: child's non-static method is called
Child.static: child's static method is called
c.static: child's static method is called
c.nonStatic: child's non-static method is called
值得注意的是p2实际上是一个Child的类型的引用,然而在调用静态方法的时候,它执行的却是父类的静态方法,而不是Child的静态方法,而调用 p2的非静态方法的时候执行的是Child的非静态方法,为什么呢?原因是静态方法是在编译的时候把静态方法和类的引用类型进行匹配,而不是在运行的时候和类引用进行匹配。因此我们得出结论:当我们在子类中创建的静态方法,它并不会覆盖父类中相同名字的静态方法。
然后用下述5个步骤来初始化这个新对象:
1)分配参数给指定的构造方法;
2)如果这个指定的构造方法的第一个语句是用this指针显式地调用本类的其它构造方法,则递归执行这5个 步骤;如果执行过程正常则跳到步骤5;
3)如果构造方法的第一个语句没有显式调用本类的其它构造方法,并且本类不是Object类(Object是所有其它类的祖先),则调用显式(用super指针)或隐式地指定的父类的构造方法,递归执行这5个步骤;如果执行过程正常则跳到步骤5;
4)按照变量在类内的定义顺序来初始化本类的变量,如果执行过程正常则跳到步骤5;
5)执行这个构造方法中余下的语句,如果执行过程正常则过程结束。
对分析本文的实例最重要的,用一句话说,就是“父类的构造方法调用发生在子类的变量初始化之前”。可以用下面的例子来证明:
列1
class Animal
{
Animal()
{
System.out.println("Animal");
}
}
class Cat extends Animal
{
Cat()
{
System.out.println("Cat");
}
}
class Store
{
Store()
{
System.out.println("Store");
}
}
public class Petstore extends Store
{
Cat cat = new Cat();
Petstore()
{
System.out.println("Petstore");
}
public static void main(String[] args)
{
new Petstore();
}
}
运行这段代码,它的执行结果如下:
Store
Animal
Cat
Petstore
从结果中可以看出,在创建一个Petstore类的实例时,首先调用了它的父类Store的构造方法;然后试图创建并初始化变量cat;在创建cat时,首先调用了Cat类的父类Animal的构造方法;其后才是Cat的构造方法主体,最后才是Petstore类的构造方法的主体。
列2
class Animal
{
Animal()
{
System.out.println("Animal");
}
}
class Cat extends Animal
{
Cat()
{
System.out.println("Cat");
}
}
class Cat2 extends Animal
{
Cat2()
{
System.out.println("Cat2");
}
}
class Store
{
Cat2 cat=new Cat2();
Store()
{
System.out.println("Store");
}
}
public class Petstore extends Store
{
Cat cat = new Cat();
Petstore()
{
System.out.println("Petstore");
}
public static void main(String[] args)
{
new Petstore();
}
}
运行这段代码,它的执行结果如下:
Animal
Cat2
Store
Animal
Cat
Petstore
这例1和例2,使我更了解了类的构造过程:
类在new实例的时候
a。第一步构造类的成员变量
这里需要注意的:
a)即使变量定义散布于方法定义之间,它们仍旧会在任何方法(包括构造函数)被调用之前得到初始化
b)初始化的顺序是先“静态”对象(初始化过后,静态对象不会再被初始化),而后是“非静态”对象。
第二步调用构造方法。
b。如果有父类,那么就是先构造父类的成员变量,然后再调用父类的构造方法,然后再a。
java中的this随处可见,用法也多,现在整理有几点:
1. this是指当前对象自己。
当在一个类中要明确指出使用对象自己的的变量或函数时就应该加上this引用。如下面这个例子中:
public class Hello
{
String s = "Hello";
public Hello(String s)
{
System.out.println("s = " + s);
System.out.println("1 -> this.s = " + this.s);
this.s = s;
System.out.println("2 -> this.s = " + this.s);
}
public static void main(String[] args)
{
Hello x=new Hello("HelloWorld!");
}
}
运行结果:
s = HelloWorld!
1 -> this.s = Hello
2 -> this.s = HelloWorld!
在这个例子中,构造函数Hello中,参数s与类Hello的变量s同名,这时如果直接对s进行操作则是对参数s进行操作。
若要对类Hello的成员变量s进行操作就应该用this进行引用
class A
{
public A()
{
new B(this).print();
}
public void print()
{
System.out.println("Hello from A!");
}
}
class B
{
A a;
public B(A a)
{
this.a = a;
}
public void print()
{
a.print();
System.out.println("Hello from B!");
}
}
public class C
{
public static void main(String[] args)
{
A x=new A();
}
}
运行结果:
Hello from A!
Hello from B!
在这个例子中,对象A的构造函数中,用new B(this)把对象A自己作为参数传递给了对象B的构造函数。
2。在构造函数中,通过this可以调用同一class中别的构造函数,如
class Flower
{
Flower (int pig)
{
System.out.println("pig:"+ pig );
}
Flower(String ss)
{
ss="string";
System.out.println("ss:"+ ss);
}
Flower(int pig, String ss)
{
this(pig);
System.out.println("pigpig"+ pig);
}
}
public class Zx
{
public static void main(String[] args)
{
Flower a=new Flower(7,"java");
}
}
运行结果:
pig:7;
pigpig:7;
1. 调用静态方法时,不需要产生对象.因为静态方法属于类本身,而不属于对象. 调用时: 类名.静态方法名() 就可以
2.
class Point
{
int x;
static int y; //定义了1个静态变量
static void output()
{
System.out.println("out");
}
public static void main(String[] args)
{
Point.output(); //调用静态方法
Point pt1=new point();
Point pt2=new point();
pt1.y=5;
pt2.y=6;
System.out.println(pt1.y);
System.out.println(pt2.y);
}
}
结果
pt1 6
pt2 6
静态常量和静态方法,都只属于某个类,加载的时候 已经有内存空间了.所有对象都共享同1个静态变量,同1个静态方法..引用直接通过类名引用.
但非静态方法,可以调用静态方法和静态变量;但反过来,静态方法不能调用非静态变量和非静态方法.(即 x)
public static void main(String[] args)
{
Aox boxobj = new Aox(25);
boxobj.bb();
boxobj=new Aox(32);
boxobj.bb();
}
}
运行结果:
25
32
public static void main(String[] args)
{
Aox boxobj = new Aox(25);
boxobj.bb();
// boxobj=new Aox(32); 出错!
boxobj.bb();
}
}