java :类和对象
一、类与对象
类:类是一个模板,描述一类对象的状态和行为;
对象:对象为类的一个实例,具有自己的属性(状态)和方法(行为);
java是一种面向对象的语言,类的基本特征有:
继承、多态、抽象、封装;
类是对象的描述,对象是类的实例;
类的声明
[public] [abstract|final] class 类名 [extends 超类名] [implements 接口名]{
成员变量;
方法;
}
public class clock{
int hour;
int minute;
public int gethour(){
return hour;
}
}
对象引用的声明
类名 引用名 = new 类名();
new 动态分配内存空间;
clock c= new clock();
数据成员:
数据类型 变量名 [= 初始值];
方法成员:
[public|private|protected|default] [static] [final] 返回类型 方法名字 (参数列表){
函数体;
}
实例变量
1、未使用static 修饰的成员变量;
2、调用只能为: 变量名.实例变量;
类(静态)变量
1、使用 static 修饰的变量;
2、调用可以为: 变量名.类变量 或者 类.类变量;
3、在整个类中只有一个值,初始化时被赋值;
4、其使用的情况为:
a、类中所有对象都相同的属性;
b、经常要共享的数据;
public class CD {
int publictime;
double price;
static String sex = new String("male"); //静态变量
public static void main(String[] args) {
CD c=new CD();
CD d=new CD();
System.out.println(c.sex+' '+d.sex+' '+CD.sex);
d.sex="female";
System.out.println(c.sex+' '+d.sex+' '+CD.sex);
}
}
// output //
male male
female female
同理,还有实例方法以及类(静态)方法;
对象的初始化
采用构造方法:
1、方法与类名相同;
2、不定义返回类型;
3、通常为public修饰符;
4、未显式声明时,生成默认的构造方法;
5、子类无法继承超类的构造器;
备注:默认的构造方法为:数值类定义为 0,字符型定义为 null;
布尔型默认为 false;
对于继承而已,子类会默认调用父类的构造器,但是如果没有默认的父类构造器,子类必须要显示的指定父类的构造器,而且必须是在子类构造器中做的第一件事(第一行代码)。
public class CD {
int publictime; // 隐式赋值;
double price;
final int nums=12; //希望该属性为常量,则采用 final 修饰;
// 初始化必须为 属性定义时或者构造函数内部;
static String sex = new String("male");
public CD(double price){ //构造函数
this.price=price; //当参数与成员变量同名时,采用this;
// this 是指当前对象;
}
public static void main(String[] args) {
CD c=new CD(2.0);
System.out.println("c.price="+c.price+" "+"c.publictime="+c.publictime);
}
c.price=2.0 c.publictime=0
可变长参数
利用一个数组来包裹要传递的实参;
二、包(package)
包是一组类的集合,可以包含多个类,也可以包含多个子包;
包的作用:
1、将相关源代码文件组织在一起;
2、命名空间的管理,划分命名空间;
3、提供包的分装和提取;
编译单元:一个java源文件称为一个编译单元;
包的引入 : import packagename. . .
一个编译单元只能有一个public类;
包的声明
package 名字
未命名的包,默认包:所有未声明包的编译单元都放在一个默认包内;
类的访问控制权限,与修饰符有关:
访问权限三、类的重用
1、 类的继承
类的继承:
1、从已包含类中生成新的类;
2、java只支持单继承,即一个子类只能有一个超类;
3、新类拥有超类所有的属性和方法(跟修饰符有关);
4、提升的代码的重用,提高抽象程度;
5、从外部看,子类拥有和超类相同的接口;
继承的语法为:
[public] class 子类名 extends 父类名 {}
class SuperClass {
private int n;
SuperClass(){
System.out.println("SuperClass()");
}
SuperClass(int n) {
System.out.println("SuperClass(int n)");
this.n = n;
}
}
class SubClass extends SuperClass{
private int n;
SubClass(){
super(300);
System.out.println("SubClass");
}
public SubClass(int n){
System.out.println("SubClass(int n):"+n);
this.n = n;
}
}
public class TestSuperSub{
public static void main (String args[]){
SubClass sc = new SubClass();
SubClass sc2 = new SubClass(200);
}
SuperClass(int n)
SubClass
SuperClass()
SubClass(int n):200
2、隐藏和覆盖
隐藏:子类对于超类继承过来的属性和方法,如果子类定义了和超类相同的成员变量,则超类被子类隐藏;
此时访问超类的成员变量,采用关键字 super;
方法的覆盖:
要求覆盖方法的访问权限可以比被覆盖权限的访问权限广,但不能更加严格;
派生类,必须覆盖超类中的抽象方法,超类中声明的final (终结方法)不能被覆盖,static方法不能被覆盖;
同时,java中所有类,直接或者间接的继承自 Object 类;
Object 类
”== " and “ equals "
Object 类的 equals 定义为:
public boolean equals(Object x){
return this == x;
}
”equals“ 表示:
两个对象永远相同的数据类型以及相同的属性值 ;
equals 需要重写;
final 类 和 final 方法
1、final修饰的类和方法;
2、终结类或方法不能被继承;
3、终结类或者方法不能被覆盖;
如String 类为终结类,终结类或者方法对系统运行较为重要,故无法被继承和覆盖;
抽象类
1、类名前加 abstract 抽象符;
2、无法进行实例化;
3、只有子类实现了超类的所有抽象属性和方法,子类才能被实例化;
结构为:
abstract class 类名{
public abstract 返回体 命名{
}
}
其优点为:
隐藏具体的细节信息,所有子类使用都含有相同的行为;
接口
1、类设计的多继承;
2、建立类与类之间的关系;
3、将类根据其实现的功能分组用作接口;
定义为:
[接口修饰符] interfce 接口名称 [extends 父接口]{
}
1、接口数据成员一点要有初值,且其值无法改变;
2、接口方法必须为抽象方法;
3、final 及 abstract 可以省;
4、接口无法实例化;
5、可以通过多继承接口,实现多继承;
集成接口的语法为
public class 类名 implements 接口名称1 接口名2{
抽象方法体的实现;
声明更多的属性及方法;
}
类的多态
类的多态:
多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。
理解多态必须理解向上转型:
public class meida {
int publictime;
double price;
static String sex = new String("male");
public meida(){
//price=21; // 类型的隐式转换
this(0,21.00);
}
public meida(int publictime,double price){
this.publictime=publictime;
this.price=price;
this.sex="female";
}
public double getprice(){
return price;
}
}
public class CD extends meida{
int like;
public CD(int a,double b){
super(a,b);
like=12;
}
public int getlike(){
return like;
}
public static void main(String[] args) {
meida c=new CD(5,21.0);
//System.out.println(c.getlike); //c为meida类,没有getlike方法
}
}
public class Wine {
public void fun1(){
System.out.println("Wine 的Fun.....");
fun2();
}
public void fun2(){
System.out.println("Wine 的Fun2...");
}
}
public class JNC extends Wine{
/**
* @desc 子类重载父类方法
* 父类中不存在该方法,向上转型后,父类是不能引用该方法的
* @param a
* @return void
*/
public void fun1(String a){
System.out.println("JNC 的 Fun1...");
fun2();
}
/**
* 子类重写父类方法
* 指向子类的父类引用调用fun2时,必定是调用该方法
*/
public void fun2(){
System.out.println("JNC 的Fun2...");
}
}
public class Test {
public static void main(String[] args) {
Wine a = new JNC();
a.fun1();
}
}
-------------------------------------------------
Output:
Wine 的Fun.....
JNC 的Fun2...
指向子类的父类引用由于向上转型了,它只能访问父类中拥有的方法和属性,而对于子类中存在而父类中不存在的方法,该引用是不能使用的,尽管是重载该方法。若子类重写了父类中的某些方法,在调用该些方法的时候,必定是使用子类中定义的这些方法(动态连接、动态调用)。
对于面向对象而言,多态分为编译时多态和运行时多态。其中编辑时多态是静态的,主要是指方法的重载,它是根据参数列表的不同来区分不同的函数,通过编辑之后会变成两个不同的函数,在运行时谈不上多态。而运行时多态是动态的,它是通过动态绑定来实现的,也就是我们所说的多态性。
当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法,但是它仍然要根据继承链中方法调用的优先级来确认方法,该优先级为:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。