【Java学习笔记】4:关于类的专题探究

来源:互联网 发布:淘宝情侣睡衣哪家好 编辑:程序博客网 时间:2024/05/29 04:47

Java中的Object类是所有类的父类。如果一个类没有使用extends关键字明确标识继承另外一个类,那么这个类就默认继承Object类。Object类是Java类层中的最高层类,因此Object类中的方法适用于所有类。

*覆写Object类的toString()方法

package day4;class Person extends Object//不写extends Object也是一样{String name="x";int age=19;//覆写toString()public String toString(){return "我是"+this.name+",今年"+this.age+"岁";}}class TestToStringDemo {public static void main(String[] args) {Person p=new Person();System.out.println(p);//实际上是System.out.println(p.toString());}}


在类的内部除了定义属性方法以外,还可以定义另一个类。这样就产生了内部类和外部类。内部类声明成private或public时,对其访问的限制与成员变量和成员方法是相同的。

内部类的定义格式:

标识符 class 外部类

{

//外部类成员

标识符 class 内部类

{

//内部类成员

}

}

*内部类的使用

package day4;class Outer{int score=95;void inst(){Inner in=new Inner();in.display();}class Inner{void display(){System.out.println("score="+score);}}}public class InnerClassDemo {public static void main(String[] args) {Outer outer=new Outer();outer.inst();}}

从上面的程序可以看到,外部类声明的属性可以被内部类直接访问,而不需要创建外部类的对象再用对象访问属性。

不过内部类声明的属性却不能被外部类访问,即其作用域仅在内部类。

和成员函数相似,用static声明的内部类不能访问非static的外部类属性。


*在类外部引用public的内部类

package day4;class Outer{int score=95;void inst(){Inner in=new Inner();in.display();}//要从外部类之外创建内部类对象,内部类要声明为publicpublic class Inner{void display(){System.out.println("score="+score);}}}public class InnerClassDemo {public static void main(String[] args) {Outer outer=new Outer();//先创建外部类对象//从外部类找到内部类Inner并创建对象inner,用外部类对象outer调用new Inner()构造函数去实例化它Outer.Inner inner=outer.new Inner();inner.display();}}

内部类不仅可以在外部类中定义,也可以在外部类的方法中定义。在方法中定义的内部类只能访问方法中的final类型的局部变量,因为用final定义的局部变量相当于一个常量,它的生命周期超出方法运行的生命周期。

*在方法中定义内部类

package day4;class Outer{int score=95;void inst(final int s)//去掉final会报错{final int temp=20;//去掉final会报错//内部类class Inner{void display(){//因为这里内部类要访问它们System.out.println("score="+(score+s+temp));}}Inner in=new Inner();in.display();}//这时在此处(函数外)却不能创建内部类的对象了}public class InnerClassDemo {public static void main(String[] args) {Outer outer=new Outer();//先创建外部类对象outer.inst(5);}}

*匿名内部类

package day4;interface A{public void fun1();}class B{int i=10;//该函数要求以实现了接口A的fun1()函数的对象为参数public void get(A a){//因为此处要求调用这个对象的fun1()函数a.fun1();}public void test(){//这里要调用类B的成员函数get,那么实参就必须是实现了接口A的fun1()函数的对象this.get(new A()//创建一个A的匿名对象{//之后实现其fun1()方法,虽然只是临时的public void fun1(){System.out.println(i);}}//将其作为实参传进get()函数里);//也就是说test()函数的功能就是调用get()函数}}public class TestInner {public static void main(String[] args) {B b=new B();b.test();}}

上述的

new A()

{

public void fun1()

{

System.out.println(i);

}

}

就是匿名内部类,它不用声明实质上的类就可以使用。


*匿名对象

package day4;class Person{private String name ="flora";private int age=19;public String talk(){return "我是:"+name+",今年:"+age+"岁";}}public class TestNoName {public static void main(String[] args) {System.out.println(new Person().talk());//用new Person()声明的对象并没有赋给任何一个Person类对象的引用//所以此对象只使用了一次,之后就会被Java的垃圾收集器回收}}

*传递和返回数组的实现过程

package day4;public class TestArray {public static void main(String[] args) {int A[][]={{51,38,82,12,34},{72,64,19,31}};//定义二维数组int B[][]=new int[2][5];//两行五列B=add10(A);//调用add10()并把返回值给数组Bfor(int i=0;i<B.length;i++)//二维的B的长度即是行数{for(int j=0;j<B[i].length;j++)//二维的B的某行的长度即是这行的列数System.out.print(B[i][j]+" ");System.out.print("\n");//换行}}public static int[][] add10(int arr[][]){for(int i=0;i<arr.length;i++)for(int j=0;j<arr[i].length;j++)arr[i][j]+=10;return arr;//将其直接返回。后面向B的赋值在java中可以自动匹配}}

运行结果:

61 48 92 22 44

82 74 29 41


Java中用引用来取代C++中的指针

*引用数据类型的传递

package day4;class Change{int x=0;}public class TestRef {public static void main(String[] args) {Change c=new Change();c.x=20;fun(c);System.out.println("x="+c.x);}public static void fun(Change c1){c1.x=25;}}

运行结果:x=25

fun()方法接收的参数Change c1,也就是说fun()方法接收的是一个对象的引用,所以在fun方法中所做的操作就会影响原来的参数。不过在函数结束后,引用c1将和它刚刚指代的那个值断开引用,但实参c却仍在生命周期内。


在今天的第一个例子中,我们覆写了Object类的toString()方法,Object类还有一个equals()方法,用于比较对象是否相等。

*没覆写前的情况

package day4;class Person{private String name;private int age;public Person(String name,int age){this.name=name;this.age=age;}}public class TestEquals {public static void main(String[] args) {Person p1=new Person("xu",19);Person p2=new Person("xu",19);//判断p1和p2的内容是否相等System.out.println(p1.equals(p2)?"是同一人":"不是同一人");}}

运行结果:不是同一人


*equals方法的覆写

package day4;class Person{private String name;private int age;public Person(String name,int age){this.name=name;this.age=age;}//覆写Object类中的equals方法public boolean equals(Object o){//声明一个p1对象,此对象实际上就是当前调用equals方法的对象Person p1=this;//判断Object类对象(第二参数)是否是Person的实例if(o instanceof Person){//如果是Person类实例,则可以向下转型(强制类型转换)Person p2=(Person)o;//调用String类中的equals方法if(p1.name.equals(p2.name)&&p1.age==p2.age)return true;}//如果不是Person类实例或者是Person类实例却不相等return false;}}public class TestEquals {public static void main(String[] args) {Person p1=new Person("xu",19);Person p2=new Person("xu",19);//判断p1和p2的内容是否相等System.out.println(p1.equals(p2)?"是同一人":"不是同一人");}}

运行结果:是同一人


接口是无法直接实例化的,因为接口中没有构造方法,但是可以通过其子类进行实例化,抽象类的道理也是一样的。

*接口对象的实例化

package day4;interface Person{public void fun1();}class Student implements Person{public void fun1(){System.out.println("Student fun1()");}}public class TestInterface {public static void main(String[] args){Person p=new Student();//用接口的子类实例化接口p.fun1();//接口具有了实例对象p并可以调用覆写后的方法new Student().fun1();//用匿名对象也可以}}

运行结果:

Student fun1()

Student fun1()


*static关键字建立公共属性

package day4;class Person{String name;static String nation="China";int age;public Person(String name,int age){this.name=name;this.age=age;}public String talk(){return "我是"+this.name+"来自"+nation;}}public class TestStatic {public static void main(String[] args) {Person p1=new Person("lzh",20);Person p2=new Person("flora",19);System.out.println("修改前:"+p1.talk());System.out.println("修改前:"+p2.talk());//只要修改某个实例的static属性,同类的其它实例也变了p2.nation="Mars";System.out.println("修改后:"+p1.talk());System.out.println("修改后:"+p2.talk());}}

运行结果:

修改前:我是lzh来自China

修改前:我是flora来自China

修改后:我是lzh来自Mars

修改后:我是flora来自Mars

也就是说static关键字用来修饰类的属性后,此属性就是公共属性了。对公共属性的修改将影响该类的全部实例。也常把用static声明的变量称之为类变量。


static用来声明方法时得到的方法称为静态方法,可以由类直接调用,也称类方法。

*static关键字建立静态方法

package day4;class Person{String name;private static String nation="China";int age;public Person(String name,int age){this.name=name;this.age=age;}public String talk(){return "我是"+this.name+"来自"+nation;}//静态方法,用来修改公共属性nationpublic static void setCity(String c){nation=c;//不应写成this.nation,因为它是公共的属性}}public class TestStatic {public static void main(String[] args) {Person p1=new Person("lzh",20);Person p2=new Person("flora",19);System.out.println("修改前:"+p1.talk());System.out.println("修改前:"+p2.talk());//静态方法可以由类直接调用,不必创建对象,这样修改公共属性才符合正常的逻辑Person.setCity("Mars");System.out.println("修改后:"+p1.talk());System.out.println("修改后:"+p2.talk());}}

运行结果:

修改前:我是lzh来自China

修改前:我是flora来自China

修改后:我是lzh来自Mars

修改后:我是flora来自Mars

注意,公共属性既可以在非静态方法中使用也可以在静态方法中使用,但静态方法却只能调用公共属性,若调用非static类型的属性就会报错。


一个类可以使用不包含在任何方法体中的静态代码块,当类被载入时,静态代码块被执行且只执行一次。静态代码块经常用来进行类属性的初始化,包括静态属性(公共属性)。

*static关键字建立静态代码块

package day4;class Person{public Person(){System.out.println("1.public Person()构造函数被执行");}//静态代码块将优先执行static{System.out.println("2.Person类的静态代码块被执行");}}public class TestStatic {public static void main(String[] args) {System.out.println("4.程序开始执行");//产生两个实例化对象new Person();new Person();//可以在结果中看到产生第二个实例化对象时静态代码块不再执行了}//静态代码块将优先执行static{System.out.println("3.主类的静态代码块被执行");}}

运行结果:

3.主类的静态代码块被执行

4.程序开始执行

2.Person类的静态代码块被执行

1.public Person()构造函数被执行

1.public Person()构造函数被执行

程序首先执行主类,所以主类的静态代码块首先执行,然后进入main函数入口,产生第一个匿名对象时要进入Person类,这时候执行Person类的静态代码块,然后再次产生对象时,Person类的静态代码块不会再执行了。也就是说只有第一次进入类时,类的静态代码块才会被执行,并且优先执行。


*final关键字的使用

①final标记的类不能被继承

②final标记的方法不能被子类覆写

③final标记的变量(成员变量或局部变量)即为常量,只能赋值一次。


*instanceof关键字的使用

可以用instanceof判断一个类是否实现了某个接口,也可以用它来判断一个实例对象是否属于一个类。instanceof的语法格式如下:

对象 instanceof 类或接口

它的返回值是boolean型的,或true或false。


参考书籍是人民邮电的《Java从入门到精通》,笔记中的多数例子和释义也是基于这本书。




0 0
原创粉丝点击