java---- 封装,接口,继承,覆盖,构造过程,多态,static、this、super、final用法
一、封装 (encapsulation)
定义:封装就是将客户端不应看到的信息包裹起来。使内部执行对外部来看不一种不透明的、是一个黑箱,客户端不需要内部资源就能达到他的目的。
1.事物的内部实现细节隐藏起来
2.对外提供一致的公共的接口――间接访问隐藏数据
3.可维护性
二、 继承 (inherit)
JAVA继承特点
继承:父类的成员能否继承到子类?
对类成员访问的限制及子类继承情况: (从严 到宽 )
private 私有,本类内部 不能继承
(default) 本类+同包 同包子类可继承
protected 本类+同包+子类 可以继承
public 公开 任何地方都可以访问 能继承到子类
覆盖
1、定义: 覆盖了一个方法并且对其重写,以求达到不同的作用。
2、用法:
a、最熟悉的覆盖就是对接口方法的实现
b、在继承中也可能会在子类覆盖父类中的方法
3、产生 “覆盖”的条件:
1、方法名:相同
2、参数表:相同(个数,类型)
3、访问限制符:相同或者更宽
4、返回值类型:相同 或者 子类返回的类型是父类返回的类型的子类
5、不能抛出比subclass(父类)更多的异常
注意:当我们在子类中创建的静态方法,它并不会覆盖父类中相同名字的静态方法。
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的非静态方法,为什么呢?原因是静态方法是在编译的时候把静态方法和类的引用类型进行匹配,而不是在运行的时候和类引用进行匹配。因此我们得出结论:当我们在子类中创建的静态方法,它并不会覆盖父类中相同名字的静态方法。
构造
(java编程思想定义为:构造器初始化)
对象的构造过程:
首先为对象分配内存空间,包括其所有父类的可见或不可见的变量的空间,并初始化这些变量为默认值,如int类型为0,boolean类型为false,对象类型为null。。。。
然后用下述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。
this用法
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;
static
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)
final
final类不能被继承,因此final类的成员方法没有机会被覆盖,默认都是final的。在
final方法不能被子类的方法覆盖,但可以被继承。
final成员变量表示常量,只能被赋值一次,赋值后值不再改变。
final不能用于修饰构造方法。
注意:父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final类型的
2、final方法
如果一个类不允许其子类覆盖某个方法,则可以把这个方法声明为final方法。
使用final方法的原因有二:
第一、把方法锁定,防止任何继承类修改它的意义和实现。
第二、高效。编译器在遇到调用final方法时候会转入内嵌机制,大大提高执行效率。
技巧:final static 类型成员变量。static使得变量只存在一个拷贝。final使得它不能改变。
public class Aox
{
int height;
Aox(int h)
{
height=h;
}
void bb()
{
System.out.println(height);
}
public static void main(String[] args)
{
Aox boxobj = new Aox(25);
boxobj.bb();
boxobj=new Aox(32);
boxobj.bb();
}
}
运行结果:
25
32
public class Aox
{
int height;
Aox(int h)
{
height=h;
}
void bb()
{
System.out.println(height);
}
public static void main(String[] args)
{
Aox boxobj = new Aox(25);
boxobj.bb();
// boxobj=new Aox(32); 出错!
boxobj.bb();
}
}
super
1.super(参数):调用基类中的某一个构造函数(应该为构造函数中的第一条语句)
2.super: 它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员数据或函数,基类与派生类中有相同成员定义时)
如:super.变量名
super.成员函数据名(实参)
包
1.从本质上来说,包是将类组合在一起形成代码模块的一种机制,可以将包看成一个“文件夹”,而包里的各类,则是“文件”。
用途:避免命名冲突;可以在更广的范围保护类,数据和方法。
2.创建包
package a; //a是包名
3.导入包
1) import package a.* //a是包名。字符"*"则导入了包里的所有类和接口。
2) import package a.b //a是包名,b是类名。该操作导入了a包里的b类,而不会导入其它类。
4.使用其它包的类,而没有用import导入该包,操作如下:
a.b x= new a.b(); //a是包名,b是a包里的类,x是刚创建的该类的实例名。