null第4课 对象和类第4课 对象和类构造
方法
快递客服问题件处理详细方法山木方法pdf计算方法pdf华与华方法下载八字理论方法下载
重载方法
覆盖方法
访问控制
static变量,方法和初始代码块
this引用的用途
final类,方法和变量
abstract类和方法,接口
解释如何以及何时使用内部类
降级,以及如何把Java程序从JDK的低版本升级到高版本
参考《Java面向对象编程》的第6、7、8和12章interface MyIFC{
void method1();
void method1(int a);
}
abstract class Base{
public void method1(){
System.out.println("hi");
}
protected abstract void method2();
}
class Sub extends Base implements MyIFC{
private int a;
private static int b;
public static final int C=1;
Sub(){this(-1);}
Sub(int a){this.a=a;}
public void method1(){a++;}
public void method1(int a){this.a=a;}
public void method2(){a--;}
public static void method3(){b++;}
}构造方法构造方法声明构造方法的语法规则
重载构造方法,参见Employee.java
默认构造方法, 参见Sample1.java
子类调用父类的构造方法,参见Son.java,
构造方法的语法规则构造方法的语法规则一个新对象的初始化的最终步骤是去调用对象的构造方法。
构造方法必须满足以下条件:
方法名必须与类名称完全相匹配;
不要声明返回类型;
不能被static、final、synchronized、abstract、native修饰。
public class Sample {
int x;
public Sample() { // No-arg constructor
x=1;
}
public Sample(int x) { //int-arg constructor
this.x=x;
}
}构造方法的语法规则构造方法的语法规则public class Sample {
int x;
public void Sample() {
x=1;
}
public static void main(String args[]){
Sample s=new Sample();
System.out.println(s.x);
}
}重载构造方法重载构造方法public class Employee {
private String name;
private int salary;
public Employee(String n, int s) {
name = n;
salary = s;
}
public Employee(String n) {
this(n, 0);
}
public Employee() {
this( " Unknown " );
}
}Employee tom=new Employee("Tom",1000);
Employee jack=new Employee("Jack");
Employee someone=new Employee();默认构造方法默认构造方法默认构造方法是没有参数的构造方法,你可以显式定义类的默认构造方法。
为了保证每个类至少有一个构造方法,如果定义的类中一个构造方法也没有写,Java将自动提供一个默认构造方法。该构造方法没有参数,用public 修饰,而且方法体为空。格式如下:
public ClassName(){}
只要类中显式定义了一个或多个构造方法,而且所有显式定义的构造方法都带参数,那么将失去默认构造方法。
默认构造方法默认构造方法public class Sample1{}
public class Sample2{
public Sample2(int a){System.out.println(“My Constructor”);}
}
public class Sample3{
public Sample3(){System.out.println(“My Default Constructor”);}
}
Sample1 s1=new Sample1();
Sample2 s2=new Sample2(); //非法
Sample2 s22=new Sample2(1);
Sample3 s3=new Sample3();子类调用父类构造方法子类调用父类构造方法在构造子类对象时,JVM会先调用父类的构造方法
子类构造方法中通过super语句调用父类构造方法
如果子类构造方法中没有通过super语句调用父类构造方法,那么JVM会调用父类的默认构造方法,如果不存在默认构造方法,将导致编译错误
子类调用父类构造方法子类调用父类构造方法class Father{
String fatherName;
Father(){
this.fatherName=“未知";
}
Father(String fatherName){
this.fatherName=fatherName;
}
}
class Son extends Father{
String sonName;
Son(String sonName){
this.sonName=sonName;
}
Son(String sonName,String fatherName){
super(fatherName);
this.sonName=sonName;
}
}
Son son1=new Son("王小毛","王大毛");
Son son2=new Son("张三");
System.out.println(son1.sonName);
System.out.println(son1.fatherName);
System.out.println(son2.sonName);
System.out.println(son2.fatherName);修饰符修饰符修饰符的类型
访问控制修饰符(public,protected,private)
static,abstract,final
修饰符的修饰内容(类,方法,变量)
修饰符的作用
使用修饰符的限制
成员变量或成员方法的访问控制成员变量或成员方法的访问控制 修饰符 同类 同包 子类 不同包
public 是 是 是 是
protected 是 是 是
默认 是 是
private 是
成员变量或成员方法的访问控制成员变量或成员方法的访问控制
包1包2public int v1;
protected int v2;
int v3
private int v4;ClassAClassBClassCClassD extends ClassAClassB, ClassC,ClassD分别可以访问ClassA的哪些成员变量?类的访问控制类的访问控制顶层类只能是public或默认访问级别
public级别的类可以被同一个包或者其他包中的类访问
默认级别的类只能被同一个包中的类访问
public class Sample{…} //public级别
class Sample{…} //默认访问级别
protected class Sample{…} //非法
private class Sample{…} //非法static关键字static关键字类(static)变量,参见Count.java
类(static)方法,参见Wrong.java
静态初始化程序,参见StaticBlock.java
静态变量和实例变量静态变量和实例变量静态变量在装载类的时候被分配内存并初始化,类只能被装载一次,所以静态变量在内存中只有一个拷贝
实例变量在创建实例时被分配内存并初始化,所以每个实例都有各自的实例变量
同一个类的实例之间共享静态变量
静态变量和实例变量静态变量和实例变量public class Count {
private int serialNumber;
private static int counter;
public Count() {
counter++;
serialNumber = counter;
System.out.println("My serialNumber is " + serialNumber);
}
public static void main(String args[]){
System.out.println("At first,counter="+ counter);
Count count1=new Count();
System.out.println("after creat count1, counter="+counter);
Count count2=new Count();
System.out.println("At last counter="+counter);
System.out.println("count1.serialNumber"+count1.serialNumber);
System.out.println("count2.serialNumber"+count2.serialNumber);
System.out.println("count1.counter"+count1.counter);
System.out.println("count2.counter"+count2.counter);
System.out.println("Count.counter"+Count.counter);
}
}
静态变量和实例变量 静态变量和实例变量堆区Count对象serialNumber=1方法区Count的类型信息counter=1count1引用变量堆区Count对象serialNumber=1方法区Count的类型信息counter=2count1引用变量count2引用变量Count对象serialNumber=2Count count1=new Count();Count count2=new Count();Count.counter//合法
Count.serialNumber//非法静态方法和实例方法静态方法和实例方法成员方法分为类方法和实例方法。用static修饰的方法叫类方法,或静态方法。
静态方法也和静态变量一样,不需创建类的实例,可以直接通过类名被访问。
static方法不能被修饰成protected和abstract。public class GeneralFunction {
public static int addUp(int x, int y) {
return x + y;
}
}
public class UseGeneral {
public void method() {
int a = 9;
int b = 10;
int c = GeneralFunction.addUp(a, b);
System.out.println("addUp() gives " + c);
}
}
静态方法和实例方法静态方法和实例方法public class Wrong {
int x;
void method(){x++;}
public static void test() {
x = 1; //非法
method();//非法
}
public static void main(String args[]) {
x = 9; //非法
method();//非法
}
}堆区Wrong对象
实例变量xWrong对象
实例变量xWrong.test() ?静态方法中不允许直接访问实例变量和实例方法静态方法和实例方法静态方法和实例方法public class Correct{
int x;
void method(){
x++; //合法
}
public static void main(String args[]) {
Correct r1=new Correct();
r1.x = 9; // 合法
r1.method();// 合法
Correct r2=new Correct();
r2.x = 10; // 合法
r2.method();// 合法
System.out.println(r1.x);
System.out.println(r2.x);
}
}堆区Correct对象
实例变量xCorrect对象
实例变量x引用变量r1引用变量r2this关键字this关键字this关键字引用当前实例
在static方法中不能使用this关键字public class Sample{
int x;
Sample(int x){
this.x=x;
method(this);
}
void method(Sample s){
s.x++; //合法
}
public static void test() {
this.x++; //非法
}
}Sample s1=new Sample(1);
Sample s2=new Sample(2);
System.out.println(s1.x);
System.out.println(s2.x);堆区Sample对象
实例变量xSample对象
实例变量x引用变量s1引用变量s2静态初始化程序静态初始化程序 类中可以包含静态代码块,它不存在于任何方法体中。当类被装载时,静态代码块只被执行一次。类中不同的静态块按它们在类中出现的顺序被依次执行。
public class Sample{
static int i = 5;
static {
System.out.println(" First Static code i= "+ i++ );
}
static {
System.out.println(" Second Static code i= "+ i++ );
}
public static void main(String args[]) {
Sample s1=new Sample();
Sample s2=new Sample();
System.out.println("At last, i= "+ i );
}
}打印
First Static code i=5
Second Static code i=6
At last,i=7 final关键字final关键字final类:不能被继承
final方法: 不能被子类覆盖
final变量:必须被显式的初始化,并且只能初始化一次,参见InitFinal0.java
public final class A{}
public class B extends A{} //非法public class A{
public final int method(){
return 1;
}
}
public class B extends A{
public int method(){ //非法
return 2;
}
}final变量
例:What will happen when compile the following code?final变量
例:What will happen when compile the following code?public class Test{
final int x = 0;
Test(){
x = 1; //非法
}
final int aMethod(){
return x;
}
}
final变量
例:What will happen when compile the following code?final变量
例:What will happen when compile the following code?1. class FinalTest{
2. final int q;
3.
4. FinalTest(){
5. this(0);
6. q = 1; }
7.
8. FinalTest(int x){
9. q = x;
10. }
11. }FinalTest f=new FinalTest();final变量
例:What will happen when compile the following code?final变量
例:What will happen when compile the following code?1. class FinalTest{
2. final int q;
3.
4. FinalTest(){}
5.
6. FinalTest(int x){
7. q = x;
8. }
9. }FinalTest f=new FinalTest();native关键字native关键字native只用来修饰方法。
native方法用其它语言(如C语言)实现,所以没有程序代码块。
public static native int myNativeMethod(int p);
extends关键字和类的继承extends关键字和类的继承继承是复用程序代码的有力手段,当多个类(Sub1,Sub2…Sub100)之间存在相同的属性和方法,可从这些类中抽象出父类Base,在父类Base中定义这些相同的属性和方法,所有的Sub类无需重新定义这些属性和方法,只需通过extends语句来声明继承Base类:
public class Sub extends Base{…}
Sub类就会自动拥有在Base类中定义的属性和方法。
Java中不支持多继承
public class ClassC extends ClassA,ClassB{} //非法
abstract关键字abstract关键字abstract修饰符可用来修饰类和成员方法:
用abstract修饰的类
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
示抽象类,抽象类位于继承树的抽象层,抽象类不能被实例化,即不允许创建抽象类本身的实例。没有用abstract修饰的类称为具体类,具体类可以被实例化。
用abstract修饰的方法表示抽象方法,抽象方法没有方法体。抽象方法用来描述系统具有什么功能,但不提供具体的实现。没有用abstract修饰的方法称为具体方法,具体方法具有方法体。
public abstract class Base{ //Base是抽象类
abstract void method1(); //抽象方法
void method2(){ //具体方法
System.out.println("method2");
}
}abstract关键字abstract关键字一个类中有抽象方法,这个类必须是抽象类
抽象类中可以没有抽象方法
abstract class Base{
abstract void method1();
abstract void method2();
}
class Sub extends Base{ //编译出错,Sub类必须声明为抽象类
void method1(){System.out.println("method1");}
} 接口接口在Java语言中,接口有两种意思:
一是指概念性的接口,即指系统对外提供的所有服务。类的所有能被外部使用者访问的方法构成了类的接口。
二是指用interface关键字定义的实实在在的接口,也称为接口类型。它用于明确的描述系统对外提供的所有服务,它能够更加清晰的把系统的实现细节与接口分离。 public interface Transparency {
public static final int OPAQUE=1;
public static final int BITMASK=2;
public static final int TRANSLUCENT=3;
public int getTransparency();
}
接口的特征接口的特征接口中只能包含public、static、final类型的成员变量和public、abstract类型的成员方法。
接口中不能有非抽象方法
public interface A{
int var; //编译出错
void method1(){System.out.println("method1");} //编译出错
protected void method2(); //编译出错
static void method3(){System.out.println("method3");} //编译出错
} 接口的特征接口的特征接口之间允许存在继承关系
interface A{
void method1();
}
interface B{
void method2();
}
interface D extends A,B{} //合法
interface E implements A,B{} //错误 接口的实现接口的实现接口由类来实现
一个类能实现许多接口。
public class MyApplet extends Applet implements
Runnable, MouseListener{
}
接口的实现接口的实现 interface SayHello {
void printMessage();
}
class SayHelloImpl implements SayHello {
public void printMessage() {
System.out.println("Hello");
}
}
接口的实现接口的实现 interface SayHello {
void printMessage();
void receiveMessage();
}
abstract class SayHelloImpl implements SayHello {
public void printMessage() {
System.out.println("Hello");
}
}
方法重载(overload)方法重载(overload)对于类的方法(包括从父类中继承的方法),如果有两个方法的方法名相同,但参数不一致,那么可以说,一个方法是另一个方法的重载方法。
重载方法必须满足以下条件:
方法名相同。
方法的参数类型、个数、顺序至少有一项不相同。
方法的返回类型可以不相同。
方法的修饰符可以不相同。
//java.lang.Math类的用于取最大值的max方法,
//有多个重载方法。
public static int max(int a,int b)
public static long max(long a,long b)
public static float max(float a,float b)
public static double max(double a,double b)int a=Math.max(1,2);
double d=Math.max(1,2.0);方法重载(overload)方法重载(overload)以下Sample类中已经定义了一个amethod()方法:
public class Sample{
public void amethod(int i, String s){}
//加入其他方法
}
下面哪些方法可以加入到Sample类中,并且保证编译正确呢?
A)public void amethod(String s, int i){} //可以
B)public int amethod(int i, String s){return 0;} //不可以
C)private void amethod(int i, String mystring){} //不可以
D)public void Amethod(int i, String s) {} //可以
E)abstract void amethod(int i); //不可以
方法覆盖(override)
方法覆盖(override)方法覆盖是指子类重新实现了父类中的方法
以下代码中子类覆盖了父类的一个方法,然后定义了一个重载方法:
public class Parent {
public void method() {System.out.println(“Parent”); }
}
public class Child extends Parent {
public void method(){System.out.println(“Child”);} //override
public int method(int a) { //overload
return 0;
}
}
方法覆盖的约束条件
方法覆盖的约束条件子类方法的名称、参数签名和返回类型必须与父类方法的名称、参数签名和返回类型一致。
public class Base {
public void method() {…}
}
public class Sub extends Base{
public int method() { //编译错误,返回类型不一致
return 0;
}
}
方法覆盖的约束条件
方法覆盖的约束条件子类方法不能缩小父类方法的访问权限,但可以扩大访问权限
public class Parent {
public void method() {
}
}
public class Child extends Parent {
private void method() { //编译错误
}
}
方法覆盖的约束条件
方法覆盖的约束条件子类方法不能抛出比父类方法更多的异常
class ExceptionA extends Exception{}
class ExceptionB extends ExceptionA{}
class ExceptionC extends ExceptionB{}
public class Parent {
void method() throws ExceptionB{}
}
public class Child1 extends Parent {
void method()throws ExceptionA {} //非法
}
public class Child2 extends Parent {
void method()throws ExceptionC {} //合法
}
多态性多态性Java语言允许某个类型的引用变量引用子类的实例,而且可以对这个引用变量进行类型转换:
Animal animal=new Dog();
Dog dog=(Dog)animal; //向下转型,把Animal类型转换为Dog类型
Creature creature=animal; //向上转型,把Animal类型转换为Creature类型
animal=new Cat();
如果把引用变量转换为子类类型,称为向下转型,如果把引用变量转换为父类类型,称为向上转型。
在进行引用变量的类型转换时,会受到各种限制。而且在通过引用变量访问它所引用的实例的静态属性、静态方法、实例属性、实例方法,以及从父类中继承的方法和属性时,Java虚拟机会采用不同的绑定机制。
多态性(参见Tester.java)多态性(参见Tester.java)class Fathers{
String var="FatherVar";
static String staticVar="StaticFatherVar";
void method(){System.out.println("Father method");}
static void staticMethod(){System.out.println("Static Father method");}
}class Sons extends Fathers{
String var="SonVar";
static String staticVar="StaticSonVar";
void method(){System.out.println("Son method");}
static void staticMethod(){System.out.println("Static Son method");}
String sonVar=null;
void sonMethod(){}
}多态性(参见Tester.java)多态性(参见Tester.java)public class Tester{
public void test(){
Fathers f=new Sons();
//Fathers f=new Fathers();
//Sons f=new Sons();
//Sons f=(Sons)new Fathers();
System.out.println(f.var);
System.out.println(f.staticVar);
f.method();
f.staticMethod();
}
public static void main(String args[]){
new Tester().test();
}
}多态性多态性参见Tester.java
对于一个引用类型的变量,编译器按照它声明的类型处理。
例如以下代码编译出错。
Fathers f=new Sons();
f.sonVar=“123”;
f.sonMethod();
如果要访问Sons的成员,必须通过强制转换:
((Sons)f).sonVar=“123”;
((Sons)f).sonMethod();
Fathersvar
method()
staticVar
staticMethod()Sonsvar
method()
staticVar
staticMethod()
sonVar
sonMethod()多态性多态性
对于一个引用类型的变量,运行时按照它实际引用的对象处理。
例如以下代码虽然编译可以通过,但运行时会抛出ClassCastException。
Fathersvar
method()
staticVar
staticMethod()Sonsvar
method()
staticVar
staticMethod()
sonVar
sonMethod()Fathers f=new Fathers();
Sons s=(Sons)f;//throw exception when runAnimal a=new Dog();
Cat c=(Cat)a;//throw exception when run多态性多态性
成员变量、静态方法按照引用变量声明的类型静态绑定;实例方法按照引用变量引用的实例动态绑定
例如,对于以下这段代码:
Fathers f=new Sons();
System.out.println(“f.var=”+f.var);
System.out.println(“f.staticVar=”+f.staticVar);
f.method();
f.staticMethod();
运行时将会输出如下结果:
f.var=FatherVar
f.staticVar=StaticFaterVar
Son method
Static Father methodFathersvar
method()
staticVar
staticMethod()Sonsvar
method()
staticVar
staticMethod()
sonVar
sonMethod()例:What will be written to the standard output when the following program is run? (参见 PolyTester.java)例:What will be written to the standard output when the following program is run? (参见 PolyTester.java)参见PolyTester.java
class Base {
int i;
Base() {add(1);}
void add(int v) {
i+= v;
}
void print() {System.out.println(i);}
}
class Extension extends Base {
Extension(){add(2);}
void add(int v) {
i+= v*2;
}
}public class PolyTester {
public static void main(String args[]) {
bogo(new Extension());
}
static void bogo(Base b) {
b.add(8);
b.print();
}
}
例:What will be written to the standard output when the following program is run? (参见 PolyTester.java)例:What will be written to the standard output when the following program is run? (参见 PolyTester.java)以上代码创建的是Extension类的实例,所以在运行时,所有调用add()方法的过程,将始终和Extension类的add()方法动态绑定。
以下是程序依次对变量i的改变过程:
初试值:i=0
step1:创建实例new Extension()
先调用父类的默认构造方法Base(),父类的默认构造方法中执行add(1),i=0+1*2 → i=2,再调用子类的默认构造方法Extension(),子类的默认构造方法中执行add(2),i=2+2*2→i=6。
step2:执行add(8)
i=6+8*2→i=22
本例子考察知识点:
方法动态绑定
子类调用父类的构造方法内部类内部类内部类,是在一个类的内部定义的类。
匿名类是一种特殊的内部类。
内部类的特性
内部类的实例化,参见InnerInit.java
内部类内部类interface OuterIFC{ void method();}
public class Outer{
public class Inner1{} //实例内部类
public static class Inner2{} //静态内部类
private OuterIFC o=new OuterIFC(){
int i=1;
void method(){i++;}
}; //一个实现了OuterIFC接口的匿名类
OuterIFC getInstance(){return o;}
void outerMethod(){
class Inner3{}; //局部内部类
Inner3 in=new Inner3();
}
}//end of class Outer
class Tester{
public void test(){
Outer.Inner1 in1=new Outer().new Inner1();
Outer.Inner1 in11=new Outer.Inner1(); //非法
Outer.Inner2 in2=new Outer().new Inner2();
Outer.Inner2 in22=new Outer.Inner2();
}
}
内部类的特性内部类的特性实例内部类可以直接访问嵌套类的成员。如果是定义在方法中的局部内部类,还可以访问该方法中的final型的局部变量和final型的方法参数。参见ClassA.java
class ClassA{
private int vA=0;
class B{int vB=vA; }
void methodA(final int param1,int param2){
final int localV=0;
class C{
int vC;
void methodC() {
int v1C=vA; //合法
int v2C=localV; //合法
int v3C=param1; //合法
// int v4C=param2; //非法
}
}//end of class C
}//end of methodA
}//end of class A 内部类的特性内部类的特性静态内部类只能直接访问所嵌套类的静态成员,而不能直接访问所嵌套类的非静态的成员,如果一定要访问,必须通过外部嵌套类的实例访问。
class A{
int vA=1;
static class B{
int vB=vA; //非法
}
}
class C{
int vC=1;
static class D{
int vD=new C().vC; //合法
}
} 内部类的特性内部类的特性实例内部类不能声明任何static成员;静态内部类中可以声明static成员。
class A{
class B{
static int var; //非法
}
}
class C{
static class D{
static int v; //合法
static class E{} //合法
}
}
C.D.v=1;
C.D.E e=new C.D.E();降级(deprecation)降级(deprecation)在版本升级时,有些类、类的构造方法或成员方法被淘汰,这成为降级。
降级(deprecation)降级(deprecation)当升级代码时,用-deprecation标志来编译代码:
javac -deprecation XXXXjava
例如编译DateConverter.javainstanceof 运算符instanceof 运算符instanceof运算符的使用形式如下:
obj instanceof ClassName 或者
obj instanceof InterfaceName
instanceof运算符的使用方法
void testType(Animal o){
if(o instanceof Dog){System.out.println(“dog”);}
if(o instanceof Cat){System.out.println(“Cat”);}
}
void test(){
Animal o1=new Dog();
testType(o1);
o1=new Cat();
testType(o1);
}
instanceof 运算符instanceof 运算符引用变量a声明为Animal类型,如果以下代码为true,引用变量a可能引用哪些类的实例?
(a instanceof Animal) && !(a instanceof Cat)CreatureAnimalCatDogCock