目录
下面我们来探讨面向对象的思想,面向对象的思想已经逐步取代了过程化的思想---面向过程,Java是面向对象的高级编程语言,面向对象语言具有如下特征
●面向对象是一种常见的思想,比较符合人们的思考习惯;
●面向对象可以将复杂的业务逻辑简单化,增强代码复用性;
●面向对象具有抽象、封装、继承、多态等特性。
面向对象的编程语言主要有:C++、Java、C#等。所以必须熟悉面向对象的思想才能编写出Java程序。
类也是一种对象
现在我们来认识一个面向对象的新的概念---类,什么是类,它就相当于是一系列对象的抽象,就比如书籍一样,类相当于是书的封面,大多数面向对象的语言都使用class来定义类,它告诉你它里面定义的对象都是什么样的,我们一般使用下面来定义类
class ClassName{
// body;
}
代码段中涉及一个新的概念 // ,这个我们后面会说。上面,你声明了一个class类,现在,你就可以使用new来创建这个对象
ClassName classname = new ClassName();
一般,类的命名遵循驼峰命名法,它的定义如下:
骆驼式命名法(Camel-Case)又称驼峰式命名法,是电脑程式编写时的一套命名规则(惯例)。正如它的名称CamelCase 所表示的那样,是指混合使用大小写字母来构成变量和函数的名字。程序员们为了自己的代码能更容易的在同行之间交流,所以多采取统一的可读性比较好的命名方式。
对象的创建
在Java 中,万事万物都是对象。这句话相信你一定不陌生,尽管一切都看作是对象,但是你操纵的却是一个对象的引用(reference)。在这里有一个很形象的比喻∶你可以把车钥匙和车看作是一组对象引用和对象的组合。当你想要开车的时候,你首先需要拿出车钥匙点击开锁的选项,停车时,你需要点击加锁来锁车。车钥匙相当于就是引用,车就是对象,由车钥匙来驱动车的加锁和开锁。并且,即使没有车的存在,车钥匙也是一个独立存在的实体,也就是说,你有一个对象引用,但你不一定需要一个对象与之关联,也就是
Car carkey;
这里创建的只是引用,而并非对象,但是如果你想要使用这个引用时,会返回一个异常,告诉你需要一个对象来和这个引用进行关联。一种安全的做法是,在创建对象引用时同时把一个对象赋给它。
Car carkey = new Car();
在Java中,一旦创建了一个引用,就希望它能与一个新的对象进行关联,通常使用 new 操作符来实现这一目的。new 的意思是,给我一个新 对象 ,如果你不想相亲,自己new 一个对象就好了。
属性和方法
类,一个最基本的要素就是有属性和方法。
属性也被称为字段,它是类的重要组成部分,属性可以是任意类型的对象,也可以是基本数据类型。例如下
class A{
int a;
Apple apple;
}
类中还应该包括方法,方法表示的是 做某些事情的方式。方法其实就是函数,只不过Java习惯把函数称为方法。这种叫法也体现了面向对象的概念。
方法的基本组成包括 方法名称、参数、返回值和方法体,下面是它的示例
public int getResult(){
// ...
return 1;
}
其中,getResult 就是方法名称、( )里面表示方法接收的参数、 return表示方法的返回值,注意∶方法的返回值必须和方法的参数类型保持一致。有一种特殊的参数类型-- void表示方法无返回值。包含的代码段被称为方法体。
构造方法
在Java中,有一种特殊的方法被称为构造方法,也被称为构造函数、构造器等。在Java中,通过提供这个构造器,来确保每个对象都被初始化。构造方法只能在对象的创建时期调用一次,保证了对象初始化的进行。构造方法比较特殊,它没有参数类型和返回值,它的名称要和类名保持一致,并且构造方法可以有多个,下面是一个构造方法的示例
class Apple{
int num;
String color;
public Apple(){}
public Apple(int num){}
public Apple(String color){}
public Apple(int num,String color){}
}
上面定义了一个Apple类,你会发现这个Apple类没有参数类型和返回值,并且有多个以Apple同名的方法,而且各个Apple 的参数列表都不一样,这其实是一种多态的体现,我们后面会说。在定义完成构造方法后,我们就能够创建Apple对象了。
class createApple{
public static void main(String[] args){
Apple apple1 = new Apple();
Apple apple2 = new Apple(1);
Apple apple3 = new Apple("red");
Apple apple4 = new Apple(3,"red");
}
}
如上面所示,我们定义了四个Apple对象,并调用了Apple的四种不同的构造方法,其中,不加任何参数的构造方法被称为默认的构造方法,也就是
Apple apple = new Apple();
如果类中没有定义任何构造方法,那么JVM 会为你自动生成一个构造方法,如下
int num;
String color;
}
class createApple{
public static void main(String[] args){
Apple apple = new Apple();
}
}
上面代码不会发生编译错误,因为Apple对象包含了一个默认的构造方法。默认的构造方法也被称为默认构造器或者无参构造器。 这里需要注意一点的是,即使JVM 会为你默认添加一个无参的构造器,但是如果你手动定义了任何一个构造方法,JVM就不再为你提供默认的构造器,你必须手动指定,否则会出现编译错误。
方法重载
在Java中一个很重要的概念是方法的重载,它是类名的不同表现形式。我们上面说到了构造函数,其实构造函数也是重载的一种。另外—种就是方法的重载
public class Apple{
int num;
String color;
public Apple(){}
public Apple(int num){}
public int getApple(int num){
return 1;
}
public String getApple(String color){
return "color";
}
}
如上面所示,就有两种重载的方式,一种是Apple构造函数的重载,一种是getApple方法的重载。但是这样就涉及到一个问题,要是有几个相同的名字,Java如何知道你调用的是哪个方法呢?这里记住一点即可,每个重载的方法都有独一无二的参数列表。其中包括参数的类型、顺序、参数数量等,满足一种一个因素就构成了重载的必要条件。
请记住下面重载的条件
●方法名称必须相同。
●参数列表必须不同(个数不同、或类型不同、参数类型排列顺序不同等)。
●方法的返回类型可以相同也可以不相同。
●仅仅返回类型不同不足以成为方法的重载。
●重载是发生在编译时的,因为编译器可以根据参数的类型来选择使用哪个方法。
方法的重写
class Fruit{
public void eat(){
System.out.println("eat fruit");
}
}
class Apple extend Fruit{
@override
public void eat(){
System.out.println("eat apple");
}
}
上面这段代码描述的就是重写的代码,你可以看到,子类Apple 中的方法和父类Fruit 中的方法同名,所以,我们能够推断出重写的原则
●重写的方法必须要和父类保持一致,包括 返回值类型,方法名,参数列表 也都一样。
●重写的方法可以使用 @0verride 注解来标识
●子类中重写方法的访问权限不能低于父类中方法的访问权限。
初始化
类的初始化
上面我们创建出来了一个Car这个对象,其实在使用new关键字创建一个对象的时候,其实是调用了这个对象无参数的构造方法进行的初始化,也就是如下这段代码
class Car{
public Car(){}
}
这个无参数的构造函数可以隐藏,由JVM自动添加。也就是说,构造函数能够确保类的初始化。
成员初始化
Java会尽量保证每个变量在使用前都会获得初始化,初始化涉及两种初始化。
●一种是编译器默认指定的字段初始化,基本数据类型的初始化
一种是其他对象类型的初始化,String 也是一种对象,对象的初始值都为null ,其中也包括基本类型的包装类。
●—种是指定数值的初始化,例如
int a = 11;
也就是说,指定a的初始化值不是0,而是11。其他基本类型和对象类型也是一样的。
构造器初始化
可以利用构造器来对某些方法和某些动作进行初始化,确定初始值,例如
public class Counter(){
int i;
public Counter(){
i = 11;
}
}
利用构造函数,能够把i的值初始化为11。
初始化顺序
首先先来看一下有哪些需要探讨的初始化顺序
●静态属性:static开头定义的属性
●静态方法块: static 包起来的代码块
●普通属性:非static定义的属性
●普通方法块:包起来的代码块
●构造函数:类名相同的方法
●方法:普通方法
public class LifeCycle{
//静态属性
private static String staticField = getStaticField();
//静态方法块
static{
System.out.println(staticField);
System.out.println("静态方法块初始化");
}
//普通属性
private String field = getField();
//普通方法块
{
System.out.println(field);
}
//构造函数
public LifeCycle(){
System.out.println("构造函数初始化");
}
public static String getStaticField(){
String statiField = "Static Field Initial";
return statiField;
}
public static String getField(){
String field = "Field Initial";
return field;
}
//主函数
public static void main(String[] args){
new LifeField();
}
}
这段代码的执行结果就反应了它的初始化顺序
静态属性初始化 静态方法块初始化 普通属性初始 化普通方法块初始化 构造函数初始化
数组初始化
数组是相同类型的、用一个标识符名称封装到一起的一个对象序列或基本类型数据序列。数组是通过方括号下标操作符 [ ] 来定义使用。
—般数组是这么定义的
int[] a1;
//或者
int a1[];
两种格式的含义是一样的。
●直接给每个元素赋值: int array[4] ={1,2,3,4};
●给一部分赋值,后面的都为0 : int array[4]= {1,2};
●由赋值参数个数决定数组的个数:int array[= {1,2};
可变参数列表
Java中一种数组冷门的用法就是可变参数,可变参数的定义如下
public int add(int... number){
int sum = 0;
for(int sum:number){
sum += sum;
}
return sum;
}
然后,你可以使用下面这几种方式进行可变参数的调用
add(); //不传参数
add(1); //传递一个参数
add(2,1); //传递多个参数
add(new Integer[] {1,2,3,4}); //传递数组