java 面向对象 上

static修饰的成员不能直接访问没有static修饰的成员

有static修饰的成员属于类本身,没有static修饰的成员属于该类的实例

static修饰的方法和成员变量既可以通过类来调用,也可以通过实例来调用。没有static修饰,只能通过实例来调用。

构造器不能定义返回值类型,也不能使用void,因为编译器会把这个当成方法来处理。实际上,构造器是有返回值的,只不过返回值是隐式的,它返回的是该类的实例。

与之前写的数组类型类似,类也是一种引用数据类型,引起定义的类型的变量实际上是引用,它被存在栈内存中,而实际的对象实例被存在堆内存中。

this有两个作用:

引用构造器中正在初始化的对象

this的最大作用就是让类中的一个方法访问该类中的另外的方法

//如果不适用this,需要创建该类的对象才能调用另一个方法
public class Person(){
    public void eat(){
    }
    
    public void sleep(){
        Person p=new Person();
        p.eat();
    }
}
public class Person{
    public void eat(){
    }
    public void sleep(){
    this.eat();
    }
}

java允许一个对象的成员直接调用另一个成员,可以省略this前缀。

对于static修饰的方法而言,可以使用类来直接调用这个方法,如果使用this,那么它并不知道指向哪一个对象。所以,静态成员不能访问非静态成员。

Java语言的方法所表现的属性如下:

方法不能独立定义,方法只能在类体中定义。

从逻辑意义上看,方法要么属于该类本身,要么属于该类的一个对象

永远不能独立执行方法,执行方法必须有类或者对象的调用

没有static修饰的方法只能使用对象来调用,不能使用类来调用\

java将实际参数值的副本(复制品)传入方法中,而参数本身不受影响

public class TestPrimitiveTransfer
{
	public static void swap(int a , int b)
	{
		int tmp = a;
		a = b;
		b = tmp;
		System.out.println("swap中的a,b"+a+" "+b);
	}
	public static void main(String[] args) 
	{
		int a = 6;
		int b = 9;
		swap(a , b);
		System.out.println("交换后的a,b"+a+" "+b);
	}
}

但在传递引用类型时,通过调用函数,会把地址传给swap 

public class TestReferenceTransfer
{
	public static void swap(DataWrap dw)
	{
		int tmp = dw.a;
		dw.a = dw.b;
		dw.b = tmp;
	}
	public static void main(String[] args) 
	{
		DataWrap dw = new DataWrap();
		dw.a = 6;
		dw.b = 9;
		swap(dw);
	}
}

局部变量会覆盖掉同名的成员变量,如果想使用被覆盖的成员变量可以用this或类作为调用者来访问成员变量

形参个数可变的方法:

void test(String ... books){
    for(String i:books);
}

构造器可以调用另一个构造器中的代码,可以使用this关键字来调用相应的构造器。例如一个有三个参数的构造器,可以调用有两个参数的构造器。通过 this(name,id),另一个变量在自己的构造器中来实现的方法来实现。

类的继承

每个类只能有一个直接的父类,实际上,类可以有无限个间接的父类

子类是对父类的扩展

class Fruit extends Plant{}
class Apple extends Fruit{}

定义一个类时并未显示指定这个类的直接父类,则这个类默认扩展java.lang.Object类。因此java.lang.Object是所有类的父类,要么是直接父类,要么是间接父类。

子类可以重写父类的方法(override)要遵循“两同两小一大”。

方法名相同,参数列表相同

子类返回值的类型应比父类的小或者相等,子类方法声明抛出的异常类应比父类小或相等

子类的访问权限应该比父类大或者相等

如果父类的一个方法具有private访问权限,因此对子类是隐藏的,所以子类无法对他进行重写

重载(overload)重写(override)的区别:

重载主要发生在同一个类中多个同名的方法中,而重载发生在子类和父类的方法中。当然,子类方法和父类方法可能发生重载,

因为子类会获得父类的方法,所以...

super用于限定该对象调用它从父类继承得到的实例变量或方法,super和this一样不能出现在static修饰的方法中。

在创建子类对象时,系统不仅会为该类中定义的实例变量分配内存,也会为从父类继承得到的实例变量分配内存。

class Parent{
	public String tag="MIT";
}
class Derived extends Parent{
	private String tag="TsingHua";
}
public class Test{
	public static void main(String[] args) {
		Derived d=new Derived();
		//程序不能访问d的私有变量,所以会引发编译错误
		//System.out.println(d.tag);
		//将d变量显示地向上转型为Parent后,可以访问
		System.out.println((Parnet)d.tag);
	}
}

子类可以调用父类的构造器,使用方法和this很像,super也必须放在第一行,区别是super调用的是父类的构造器,this调用的是同一个类的构造器。不管是否使用super调用来执行父类构造器的初始化代码,子类总会调用父类构造器一次。

当调用子类构造器时,父类构造器总会在子类构造器之前执行,不进如此,父类构造器还会上溯执行其父类构造器....所以最先执行的总是java.lang.Object 类的构造器

多态

编译时类型和运行时类型不同,就称为多态(Polymorphism)

允许把子类对象直接赋给一个父类引用变量,无须任何类型转换,或者称为向上类型(upcasting)

与方法不同的是,对象的实例变量不具备多态性

引用变量在编译阶段只能调用编译类型所具有的方法,但运行时执行它运行时类型所具有的方法。

类型转换:

数值类型和布尔类型不能进行类型转换

引用类型之间的转换只能在有继承关系的两个类型之间进行。如果把父类转换成子类,则这个对象必须是子类实例才行(编译时为父类类型,运行时为子类类型)否则将引发ClassCastException。

当把子类赋值给父类引用变量时,被称为向上转型(upcasting),这种转型总是成功的

在进行强制类型转换之前,先用instanceof可以判断能否成功转换,避免了异常。instanceof用于判断前面的对象是否是后面的类,子类,实现类的实例。

初始化块在创建对象时隐式执行,而且在构造器之前,一个类只能定义两个。

用法:如果一段初始化代码对所有对象相同,且无需接受任何参数,就可以放在初始代码块中。

创建对象时,不仅会执行该类的初始化块和构造器,而且系统会一直追溯到java.lang.Object类,先执行java.lang.Object类的初始化代码块,然后再执行java.lang.Object的构造器,然后再向下执行。

当初始化块使用static修饰符,则这个初始化块就变成了静态初始化块。普通初始化块负责对对象进行初始化,类初始化块负责对类进行初始化。将在类被创建的时候执行静态初始化块,而不是在创建对象的时候执行。不能访问非静态成员。与普通初始化块类似,在类初始化阶段,需要一直上溯到java.lang.Object类,先执行java,lang.Object类的静态初始化快...最后再执行该类的静态初始化块。

静态初始化块只会在类被创建的时候使用,而不会每次创建实例的时候使用。

猜你喜欢

转载自blog.csdn.net/albert48/article/details/83578690