java面向对象
三大特性:继承、封装、多态
对象的特征(属性),对象的行为(方法)
public class Car{
String color;
int num;
public void run()
{
syso("car running~~")
}
}
类名 对象名=new 类名();
public class Car {
String color;
int num;
public void run() {
System.out.println("小汽车颜色"+color+"轮子有"+num);
}
}
public class emm01 {
public static void main(String[] args) {
Car c1=new Car();
c1.color="red";
c1.num=4;
c1.run();
}
}
类的封装:
在定义一个类时将类中的属性进行私有化,即使用private关键字进行修饰,私有化属性只能在当前所在类中被访问,如果外界想要访问私有属性,要提供一些public修饰的公共方法,其中包括用于获取属性值的getter方法和设置属性值的setter方法。
public class Car {
private String color;
private int num;
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getNum() {
return num;
}
public void setNum(int num) {
if (num!=4)
{
System.out.println("error");
}
else {
this.num = num;
}
}
public void run() {
System.out.println("小汽车颜色"+color+"轮子有"+num);
}
public static void main(String[] args) {
Car c1=new Car();
c1.setColor("blue");
c1.getColor();
c1.setNum(0);
c1.getNum();
c1.run();
}
构造方法的定义
在实例化对象赋值时,不仅可以通过setter方法完成,还可以通过构造方法完成.所谓的构造方法是类的一个特殊成员,他会在类实例化对象时被自动调用.在定义构造方法时,
必须满足以下三个条件:
1.方法的名称和类名必须相同.
2.在方法名称前没有返回值类型的声明.
3.在方法体中不可以使用return 语句返回一个值,但是允许单独写return 语句作为方法的结束.
public Car() {
System.out.println("无参构造");
}
有参构造:
public class Car {
String color;
public Car(String color) {
this.color=color;
}
public void run()
{
System.out.println("这车颜色"+color);
}
}
构造方法的重载:
构造方法与普通方法一样也可以实现重载,由于构造方法的方法名和类名相同,因此只要每个构造方法的参数类型和参数个数不同即可实现构造方法的重载.在创建实例对象时,可以通过调用不同的构造方法为不同的属性进行赋值.下面通过案例学习构造方法的重载...
public class Car {
String color;
int num;
public Car(String color) {
this.color=color;
}
public Car(String color,int num)
{
this.color=color;
this.num=num;
}
public Car() {
System.out.println("空构造");
// TODO Auto-generated constructor stub
}
public void run()
{
System.out.println("这车颜色"+color+"轮子数"+num);
}
}
public static void main(String[] args) {
Car c1=new Car("blue");
Car c2=new Car();
Car c3=new Car("red",4);
c1.run();
c2.run();
c3.run();
}
this 关键字: 表示当前对象 三种常见的用法
(1)public Car(String color,int num)
{
this.color=color;
this.num=num;
}
(2)public class Car {
protected/private void ccc()
{
System.out.println("protect");
}
public void run()
{
this.ccc();
}
}
(3)在构造方法中 可以使用this([参数一],[参数二]);
来调用其他的构造函数
public Car(int id,int age)
{
this.age=age;
this.id=id;
}
public Car(String sex,int id,int age)
{
this(id,age);
this.sex=sex;
}
static 关键字:
静态变量:如果使用一个类,则会在产生实例化对象时分别在堆内存中分配空间,在堆内存中要保存对象中的属性,每个对象都有自己的属性,如果有些属性希望被所有对象共享,
就必须使用static 关键字修饰成员变量,该变量被称为静态变量,可以直接使用"类名.变量名"的形式调用
public class Car {
static String carName="byd"; //成员变量 静态化 可以类名. 进行访问
}
Car c1=new Car();
Car.carName="bwm";
System.out.println(Car.carName);
System.out.println(c1.carName);
static 关键字只能用于修饰成员变量,不能用于修饰局部变量,否则编译会报错,如:
public class Car{
public void run()
{
static int number=4; //这行代码是非法的,编译会报错
}
}
静态方法:
要想调用某个方法,必须要创建一个对象,有没有一种方法可以不创建对象就能直接调用呢?实际上有一种方法可以这样操作,那就是静态方法,
静态方法和普通方法的区别是在方法前面加一个static关键字,这种方法称为静态方法.同静态变量一样,静态方法可以使用"类名.方法名"的方式访问,也可以通过类的实例对象访问.
public static void run() {
System.out.println("run........");
}
Car c1=new Car();
Car.run();
c1.run();
注意:在一个静态方法中只能访问用static修饰的成员,原因在于没有被static修饰的成员需要先创建对象才能访问,而静态方法在被调用时不需要创建任何对象.
静态代码块:
在java类中,使用一对大括号包围起来的若干行代码被称为一个代码块,用static关键字修饰的代码块称为静态代码块.
当类被加载时,静态代码块会被执行,由于类只能加载一次,所以静态代码块也只会执行一次.在程序中,通常会使用静态代码块对类的成员变量进行初始化.
static String color;
static {
color="red";
System.out.println("这辆车的颜色是"+color);
}
public Car() {
// TODO Auto-generated constructor stub
System.out.println("无参构造");
}
Car c1=new Car();
Car c2=new Car();
这辆车的颜色是red
无参构造
无参构造
结果表明:创建类的对象时,先加载静态代码块再加载构造函数,在两次创建对象的过程中,静态代码块只输出了一次,说明静态代码块中类中只加载一次.
类的继承:
extends 关键字 若类没有继承任何类则默认继承Object类,Object类是所有类的父类.
注意:在类的继承中:
(1)在Java中,类只支持单继承,不允许多重继承,也就是说一个类只能有一个直接的父类.
(2)多个类可以继承一个父类.
(3)在Java中,多层继承是允许的,即一个类的父类可以再继承其他的父类.
重写父类方法
在继承关系中,子类会继承父类中定义的方法,但子类也可以在父类的基础上拥有自己的特征,即对父类的方法进行重写.需要注意的是,在子类中重写的方法必须与父类被重写的方法具有相同的方法名,参数列表以及返回值类型...
public class Animal {
public void sleep()
{
System.out.println("sleeping");
}
public void call()
{
System.out.println("calling");
}
}
public class Cow extends Animal {
public void call() {
System.out.println("mou!!!!");
}
}
Cow c1=new Cow();
c1.call();
c1.sleep();
当子类继承父类时,会拥有父类中所有的成员,由此可知,在调用sleep()方法时,会自动调用父类的sleep()方法.当子类重写了父类方法只后,会调子类重写后的call()方法.
注意:子类重写父类方法时,不可以使用比父类中被重写的方法更严格的访问权限,如父类的方法是public 的,子类的方法就不可以使private的!
super关键字
当子类重写了父类的方法后,子类对象将不能访问父类被重写的方法.为了解决这个问题,在Java 中专门提供了super关键字用于访问父类的成员变量/成员方法和构造方法.格式如下:
super.成员变量 //访问成员变量
super.成员方法([参数1,参数2,...]) //访问成员方法
super([参数1,参数2]) //访问构造方法
public class Animal {
public Animal(String name) {
System.out.println("我是一头小"+name);
}
}
public class Cow extends Animal {
public Cow()
{
super("黄牛");//调用父类含参构造方法
}
}
public static void main(String[] args) {
Cow c1=new Cow();
}
注意:通过super关键字调用父类构造方法的代码 必须位于子类构造方法的第一行,并且只能出现一次..
final关键字:
在Java中,如果父类的某些方法不希望再被子类重写,则必须把它们修饰为最终方法.即使用final修饰.final关键字可以用于修饰类、变量和方法,表示不能改变或者最终。因此final修饰的类、变量和方法具有以下特性。:
*final修饰的类不能被继承
*final修饰的方法不能被子类重写
*final修饰的变量(成员变量和局部变量)是常量,并且只能赋值一次。
抽象类和接口
抽象类:在Java程序中,允许在定义方法时不写方法体,这种方法被称为抽象方法,抽象方法必须使用abstract关键字修饰.抽象方法的出现,解决了程序中某些方法的不确定实现.例如前面在定义Animal类时,call()方法用于表示动物的叫声,但是针对不同的动物,叫声也是不同的,因此在call()方法中无法准确描述动物的叫声,抽象方法的语法格式如下:
abstract void call(); //定义抽象方法call()
如果一个类中定义了抽象方法,那么该类必须定义为抽象类,抽象类也同样使用abstract 关键字修饰,如:
abstract class Animal{
abstrct void call();}
需要注意的是,包含抽象方法的类必须声明为抽象类 ,但是抽象类可以不包含任何抽象方法,只需要使用abstract关键字修饰即可.另外,抽象类是不可以被实例化的,因为抽象类中有可能包含抽象方法,抽象方法是没有方法体的,不可以被调用.如果想调用抽象类中定义的方法,需要创建一个子类,在子类中将抽象类中的抽象方法进行实现...
public abstract class Animal {
public abstract void call();}
public class Cow extends Animal {
public void call() {
System.out.println("mou!!!"); }}
Cow c1=new Cow();c1.call();
接口
在Java中还存在一种特殊的抽象类,该类中只存在常量和抽象方法,而不存在变量的定义和方法实现,这种特殊的类被称为接口.接口是由常量和抽象方法组成的特殊类,是对抽象类的进一步抽象.定义接口时,需要使用interface关键字.
接口中的全局变量默认使用了"public static final"修饰,抽象方法默认使用了"public abstract"修饰.需要注意的是,在接口定义方法时,所有的方法必须都是抽象的,所以不能通过实例化对象的方式调用接口中的方法.此时需要定义一个类,并使用implements关键字实现接口中的所有的方法.
interface Animal{
String ANIMAL_ACTION="动物的行为动作";//默认public static final
void call();// 默认public abstract}
Cow类实现了Animal接口后是可以被实例化的,并且实例化后就可以调用Cow类中的方法.需要注意的时,一个类实现一个接口,必须实现接口重的所有的方法,如果不能实现某个方法,则必须写出一个空实现的方法.
接口的特性归纳:
-
接口的访问限定只有public 和默认.
-
interface 是声明接口的关键字,与class类似
-
允许接口的多重继承,通过"extends父接口名"的形式可以继承多个接口,接口之间用逗号, 隔开
-
在接口中定义的常量,系统默认是public static final修饰的,不需要指定.
-
接口中的方法都是抽象的,不能实例化对象.
多态
多态就是指在同一个方法中,由于参数类型不同而出现执行效果各异的现象.例如在实现动物叫的方法中,由于每种动物的叫声不同,因此可以再方法中接受一个动物类型的参数,当传入具体的某个动物时发出具体的叫声.在Java中为了实现多态,允许使用父类类型的变量引用一个子类类型的对象,根据子类对象特征的不同,得到不同的运行结果.
interface Animal{
void call();// 默认public abstract}
public class Cow implements Animal {
public void call() {
System.out.println("mou!!!"); }}
public class sheep implements Animal {
public void call() {
System.out.println("mie!!!!"); }}
public static void main(String[] args) {
Animal a1=new Cow();//创建Cow对象,使用Animal 类型的变量a1引用
Animal a2=new sheep();//创建sheep对象,使用Animal 类型的变量a2引用
animal_call(a1);
animal_call(a2);
}
public static void animal_call(Animal animal) {
animal.call();}
对象的类型转换
在多态的学习中,涉及将子类对象当作父类类型使用的情况,此种情况在Java的语言环境中称为"向上转型"
Animal a1=new Cow();//创建Cow对象,使用Animal 类型的变量a1引用
Animal a2=new sheep();//创建sheep对象,使用Animal 类型的变量a2引用
需要注意的是,将子类对象当作父类对象使用时,不需要任何显式转换,但此时不能通过父类变量调用子类中的特有方法.
注意:不可以向下转型 如: Animal a=new sheep(); func(Animal a) ; Cow c=Cow (a);会报错
针对这种情况,Java提供了一个关键字instanceof , 它可以判断一个对象是否为某个类(或者接口)的实例或者子类实例,语法格式如下:
对象(或者对象引用变量) instanceof 类 (或接口)
public static void animal_call(Animal animal) {
if (animal instanceof Cow)
{
Cow cow=(Cow) animal;
cow.call();
}
else System.out.println("animal is not cow");
}
从上述代码可以看出,可以使用instanceof关键字判断 aniamlCall() 方法中传入的对象的类型,如果是Cow类型则进行强制类型转换,否则输出 not .
匿名内部类:
在前面的多态讲解中,如果方法的参数被定义为一个接口类型,那么就需要定义一个类实现接口,并根据该类进行对象实例化.除此之外,还可以使用匿名内部类实现接口.当程序中使用匿名内部类时,定义匿名内部类的地方往往直接创建该类的一个对象.匿名内部类的格式如下:
new 父类(参数列表) 或 父接口(){
//匿名内部类实现部分
}
animalCall(
new Animal()
{public void call() {System.out.println("mou@@");}}
);//匿名内部类实现抽象方法
public static void animalCall(Animal a) {
a.call();
}
调用animalCall()方法时,在方法的参数位置写上了new Animal() {},这相当于创建了一个实例对象,并将对象作为参数传递给animalCall()方法.在new Animal()后边有一对大括号,表示创建了Animal的子类对象,该子类是匿名的...
异常
在程序运行的过程中,可能会发生异常(Exception)情况,例如运行时内存溢出,磁盘空间不足,网络中断等.针对此类状况,Java中提供了异常处理机制,以异常类的形式对这些不正常的情况进行封装,通过异常处理机制对代码发生的各种问题进行有针对性的处理.
常见的异常类
由图可以看出,Throwable由两个直接子类Error 和Exception ,其中Error表示程序代码中出现的错误,Exception 表示程序代码中出现的异常,二者的区别在于,错误表示系统内部错误或资源耗尽的错误,仅靠程序本身是不能恢复执行的,而异常表示程序本身可以处理的错误..
try ...catch 和finally
异常捕获:
try {
//程序代码块
}catch(异常类型(Exception类或者其子类) 变量名){
//对异常的处理}
在上述代码中,try代码块用于编写可能发生异常的Java语句,catch代码块用于编写针对异常进行处理的代码.当程序发生异常时,系统会将异常信息封装成一个对象传递给catch代码块,catch代码块需要一个Exception类型的参数进行接收..
在处理异常时,我们偶尔也希望无论程序是否发生异常都要执行某个特定语句,此时就需要在try ...catch 后面加上一个finally语句,无论程序是否发生异常,finally语句中的内容都会执行.
try {
int res=calculate(5,0);
System.out.println(res);
}
catch (Exception exception){
System.out.println("捕获的异常是"+exception.getMessage());
return;
}
finally {
System.out.println("finally");
}
System.out.println("runing");
}
public static int calculate(int a,int b)
{
int res =a/b;
return res ;
}
在catch代码块中增加了一个return语句,用于终止当前方法的执行,此时程序的running 就不会执行了,但是finally中的代码仍会执行,说明finally 中的代码不会被return 语句影响.通常情况下,会在finally代码块中完成关闭系统资源等操作..
throws 关键字
在上节中已经了解到异常的发生可以使用try...catch 语句的方式进行处理,除了此方法以外,在Java中还提供了另一种对异常的处理方式,即抛出异常.抛出异常使用throws 关键字对外声明该方法有可能发生的异常,这样在调用方法时,就很清楚该方法是否有异常,并必须对异常进行针对性的处理,否则编译失败.
修饰符 返回值类型 方法名 ([参数1,参数2...])throws ExceptionType1[,ExceptionType2...]{
}
从上述语法格式中可以看出,throws 关键字需要写在方法声明的后面,并且在throws后面需要声明方法中发生异常的类型,通常将这种做法称为方法声明抛出异常..
注意:在程序开发中有两种常见异常,一种是编译时异常,另一种是运行时的异常,区别是编译时产生的异常必须进行处理,否则编译不通过,而运行时的异常是在程序运行中产生的,即使不进行异常处理也能通过编译.
访问控制
private-> default-> protected-> public
访问级别由小到大
private (类访问级别):表示私有的,使用private修饰的成员只能被该类的其他成员访问,其他类无法直接访问.
default(包访问级别):若没有访问修饰符,则系统默认使用default .该类可以被本类包中的所有类访问.
protected(子类访问级别):表示受保护的,该类可以被同一包下的其他类访问,也能被不同包下的子类访问
public(公共访问级别):表示公有的,该类或者类中的成员可以被所有的类访问..
访问范围 | private | default | protected | public |
同一类中 | ✔ | ✔ | ✔ | ✔ |
同一包中 |
| ✔ | ✔ | ✔ |
子类中 |
|
| ✔ | ✔ |
全局范围 |
|
|
| ✔ |