类是用于描述同一类型的对象的一个抽象。类中定义了这一类对象所具有的静态和动态属性
静态属性:成员变量
动态属性:方法
1 类可以看成是一类对象的模板,对象可以看成该类的一个具体实例
2 首先必须定义类才能有对象
说到类,就不得不说构造其构造方法了
在new一个对象是,调用的就是类中的构造方法
列如
public class Person {
int age;
Person (int _age) {
age = _age;
}
public static void main (String[] args) {
Person p1 = new Person(20);
}
}
首先,会在栈内存中存在存放p1的地址,调用构造方法后,会在栈内存中存在局部变量_age,并为其赋值20,方法调用完后,在堆内存中会有一块内存,其中存放age成员变量,并将_age的值传递给age,传递完成后,_age局部变量消失,栈内存中存放p1的地址指向堆内存中存放属性的那块
new过程就是调用类的构造函数,若类没有定义构造函数,则系统会自动添加无参数的构造函数,若类自身定义了构造函数,则系统不会再添加构造函数
方法的重载
方法的重载只能用参数表来区分,返回值类型不能用来区分重载的方法
1参数个数
2参数类型
静态变量存放在数据区data seg,不管有多少对象,或者没有对象,data seg中都存在
静态变量属于整个类,可以用类名访问,在第一次使用时被初始化
静态方法:在调用静态方法时,不会将对象的引用传递给它,所以静态方法不可访问非静态成员
给包取名
1 前缀包名法:一般用来区别不同包中名称相同的类
2 import法
访问同一个包内的类不用访问
sun提供了很多java类包,其中java.lang包内的类不需要引用,其他包需要引入
当别人要用到自己的程序是,可以将所有文件夹压缩为jar包使用,sun提供的各种java类包可以在jre下lib文件夹中找到,其名称为rt.jar,将其解压后可以看到
用Dos命令 jar –cvf 名称 *.* 可以将文件夹压缩为jar包使用
(*.*的意思为将该文件夹下的所有文件打包)
访问修饰符
访问修饰符可以修饰成员变量,成员方法,也可以修饰类
修饰符 类内部 同一个包 子类 任何地方
private Yes
default Yes Yes
protected Yes Yes Yes
public Yes Yes Yes Yes
定义方法,成员变量,类时未指明访问修饰符是,为默认,即default,也叫包权限,只可以被同一个包中的类访问
Class只能被public和default修饰
继承
当new一个对象时,内存中会有一个this指针指向自身
若是子类,同时内存中会有一个super指针指向父类
如果子类在构造过程中没有显示调用父类中的构造方法,则默认调用父类无参构造方法
如果子类在构造过程中没有调用父类的构造方法,而父类中又没有无参的构造方法,则编译出错
在子类构造时,必须调用父类的构造方法
假如父类中没有定义构造方法,系统会默认一个无参的构造方法,但是假如你父类中定义了一个有参的构造方法后,也必须定义一个无参的构造方法,因为在子类实例化的时候如果调用了父类的无参构造方法,但是父类中却没有这个无參的构造方法,系统编译会报错。
。
Object是所有类的基类
类对象之间的类型转换
1一个基类的引用类型变量可以“指向”其子类的对象
2一个人基类的引用不可以访问其子类新增加的属性(成员和方法)
3可以使用 引用变量instanceof类名 来判断该引用型变量所“指向”的对象是否属于该类或该类的子类
instanceof关键字作用,测试它左边的对象是否是他右边的类的实例,返回 boolean类型的数据,可以用在继承中的子类的实例是否为父类的实现
instanceof探索的是该类型在内存中具体存在的类型,而不是其引用类型
可以用于判断父类对象是不是子类对象的实例
class Animal {
public String name;
Animal(String name) {
this.name = name;
}
}
class Dog extends Animal {
public int Id;
Dog (String name, int Id)
{
super(name);
this.Id = Id;
}
public static void main (String[] args) {
Animal a = new Animal("small");
Animal b = new Dog ("big", 1); //父类对象为子类的实例化
}
}
用instanceof
a instanceof Dog为false
b instanceof Dog为true
基类转换为子类时,编译不会错,但运行时会出现异常
子类转换成基类时,然后使用强制类型转换为原来的子类类型,数据不会丢失。
基类对象为子类的实例化时,不可以访问子类中新的属性,但是通过强制类型转换,列如Dog c = (Dog)b,对象c可以访问b中原来无法访问的属性
多态(面向对象的核心,使程序扩展达到了极致)
1 静态:同一类中方法的重载 (在编译时进行)
2 动态:子类对父类方法的重写(覆盖)(在执行时进行):
存在的条件:1继承 2 重写 3父类引用指向子类对象
列如
class Father {
public void print() {
System.out.println("Father");
}
}
class Son extends Father { //继承
public void print() { //重写
System.out.println("Son");
}
}
class TT {
public void testPrint(Father a) {
a.print();
}
}
class Test{
public static void main(String[] args) {
Father a = new Son(); //父类引用指向子类对象
TT b = new TT();
b.testPrint(a);
}
}
打印出的son
说明程序执行过程中,是根据其实际类型来确定调用的哪个类的方法
该机制使程序扩展达到了极致,若添加类,只需继承父类,重写父类中的相关方法,而不用特别大的改动,(相对面向过程语言)
抽象类
用关键字abstract修饰的方法和类叫做抽象方法和抽象类
抽象类不一定有抽象方法,但含有抽象方法的类必须声明为抽象类
1抽象类只含有方法头,即只需要声明。 public abstract void print();
2抽象类不能实例化对象
注意点:
1abstract不能修饰构造方法
2static,private,final不能与abstract组合使用
static在类实例化前会先被实例化,而abstract不能用于实例化对象,矛盾
private为私有,子类继承父类是无法重写私有方法,而abstract需要子类继承,通过重写才能使用,两者在一起就是无法继承的抽象方法,即使存在也无实际意义(个人见解)
final和abstract不能修饰同一个类,abstract 不能实例化,只能在派生的子类的获得应用,而final修饰的类不能拥有子类,两者同时修饰的类无法使用。
final关键字
final可用于修饰类,方法,变量
1 final修饰类时,无法派生子类
2 final修饰的变量一旦赋值则无法改变其值,即使是相同的值
3 final修饰的方法无法重写
可以认为final修饰的一经赋值,就是只读的
在用final做实验时,也发现了几个原来未曾注意的问题
final变量作为成员变量时,一定要显示初始化,要么为其赋初值,要么在构造方法中定义final变量
还可以在初始化块中初始化
Final变量作为局部变量时.可以只定义不初始化
class T {
final int i = 0;//正确
}
class T {
final int i;
i = 0; //错误 该错误适用于任何所有数据类型
}
class T {
final int i;
T ()
{
I = 0 ;
}
}//正确
我的理解:在类中可以定义final变量,并在构造方法中对其赋值
因为每个对象对应一个不同的final变量
但是,一经赋值后,无法改变
静态初始化
class T {
final static int i;
static {
i = 0;
}
}