面试官:Java的特点了解多少?
你:1、“抽象”,把现实世界中的某一类东西,提取出来,用程序代码表示;2、“封装”,把过程和数据包围起来,对数据的访问只能通过已定义的界面;3、“继承”,一种联结类的层次模型;4、“多态”,允许不同类的对象对同一消息做出响应。
面试官:那面向对象的特征呢?
你:
哈哈,把面试官问题搞混了把(其实也没差,有些面试官爱咬文嚼字)下面我们就开始(顺便给重载重写处理了)
Java的特点:1、面向对象;它对对象中的类、对象、继承、封装、多态、接口、包等均有很好支持。2、平台无关性;在引入虚拟机之后,Java语言在不同的平台上运行不需要重新编译。3、简单性。4、解释执行;程序在Java平台运行时会被编译成字节码文件,然后可以在有Java环境的操作系统上运行。5、支持多线程,并提供多线程之间的同步机制;6、分布式;7、健壮性;8、高性能;9、安全性。
面向对象的特征是:1、“抽象”,把现实世界中的某一类东西,提取出来,用程序代码表示;2、“封装”,把过程和数据包围起来,对数据的访问只能通过已定义的界面;3、“继承”,一种联结类的层次模型;4、“多态”,允许不同类的对象对同一消息做出响应。
Java 继承
哈哈就是这样,那么代码怎么写??
1 class 父类 { 2 }
1 class 子类 extends 父类 { 2 }
示例
公共父类:
看以上图片
public class Animal { private String name; private int id; public Animal(String myName, int myid) { name = myName; id = myid; } public void eat(){ System.out.println(name+"正在吃"); } public void sleep(){ System.out.println(name+"正在睡"); } public void introduction() { System.out.println("大家好!我是" + id + "号" + name + "."); } }
子类
public class Coat extends Animal { public Penguin(String myName, int myid) { super(myName, myid); } }
但可以实现多个接口
继承的特性 子类拥有父类非 private 的属性、方法。 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。 子类可以用自己的方式实现父类的方法。 Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 B 类继承 A 类,C 类继承 B 类,所以按照关系就是 B 类是 C 类的父类,A 类是 B 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。
extends关键字
在 Java 中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类,所以 extends 只能继承一个类。
public class Animal { private String name; private int id; public Animal(String myName, int myid) { //初始化属性值 } public void eat() { //吃东西方法的具体实现 } public void sleep() { //睡觉方法的具体实现 } } public class Penguin extends Animal{ }
implements关键字
使用 implements 关键字可以变相的使java具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔)。
public interface A { public void eat(); public void sleep(); } public interface B { public void show(); } public class C implements A,B { }
super 与 this 关键字
super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
this关键字:指向自己的引用。
1 class Animal { 2 void eat() { 3 System.out.println("animal : eat"); 4 } 5 } 6 7 class Dog extends Animal { 8 void eat() { 9 System.out.println("dog : eat"); 10 } 11 void eatTest() { 12 this.eat(); // this 调用自己的方法 13 super.eat(); // super 调用父类方法 14 } 15 } 16 17 public class Test { 18 public static void main(String[] args) { 19 Animal a = new Animal(); 20 a.eat(); 21 Dog d = new Dog(); 22 d.eatTest(); 23 } 24 }
final 关键字
final 关键字声明类,不能被继承 、用于修饰方法,该方法不能被子类重写
final 可以用来修饰变量(包括类属性、对象属性、局部变量和形参)、方法(包括类方法和对象方法)和类。
final 含义为 "最终的"。
声明类: final class 类名 {//类体} 声明方法: 修饰符(public/private/default/protected) final 返回值类型 方法名(){//方法体}
构造器
子类是不继承父类的构造器(构造方法或者构造函数)的,它只是调用(隐式或显式)。如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表。
如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器。
class SuperClass { private int n; SuperClass(){ System.out.println("SuperClass()"); } SuperClass(int n) { System.out.println("SuperClass(int n)"); this.n = n; } } // SubClass 类继承 class SubClass extends SuperClass{ private int n; SubClass(){ // 自动调用父类的无参数构造器 System.out.println("SubClass"); } public SubClass(int n){ super(300); // 调用父类中带有参数的构造器 System.out.println("SubClass(int n):"+n); this.n = n; } } // SubClass2 类继承 class SubClass2 extends SuperClass{ private int n; SubClass2(){ super(300); // 调用父类中带有参数的构造器 System.out.println("SubClass2"); } public SubClass2(int n){ // 自动调用父类的无参数构造器 System.out.println("SubClass2(int n):"+n); this.n = n; } } public class TestSuperSub{ public static void main (String args[]){ System.out.println("------SubClass 类继承------"); SubClass sc1 = new SubClass(); SubClass sc2 = new SubClass(100); System.out.println("------SubClass2 类继承------"); SubClass2 sc3 = new SubClass2(); SubClass2 sc4 = new SubClass2(200); } } 输出结果为: ------SubClass 类继承------ SuperClass() SubClass SuperClass(int n) SubClass(int n):100 ------SubClass2 类继承------ SuperClass(int n) SubClass2 SuperClass() SubClass2(int n):200
Java 封装
在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。
封装的优点 1. 良好的封装能够减少耦合。 2. 类内部的结构可以自由修改。 3. 可以对成员变量进行更精确的控制。 4. 隐藏信息,实现细节。
常见的封装
//对属性的访问(一般限制为private),例如: public class Person { private String name; private int age; } //创建一对赋取值方法,用于对私有属性的访问 public class Person{ private String name; private int age; public int getAge(){ return age; } public String getName(){ return name; } public void setAge(int age){ this.age = age; } public void setName(String name){ this.name = name; } }
Java 抽象类
在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。
父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。
在 Java 中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。
在 Java 语言中使用 abstract class 来定义抽象类。如下实例:
public abstract class Employee { }
继承抽象类
/* 文件名 : Salary.java */ public class Salary extends Employee { }
抽象类总结规定 1. 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。 2. 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。 3. 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。 4. 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。 5. 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。
抽象方法
如果你想设计这样一个类,该类包含一个特别的成员方法,该方法的具体实现由它的子类确定,那么你可以在父类中声明该方法为抽象方法。
Abstract 关键字同样可以用来声明抽象方法,抽象方法只包含一个方法名,而没有方法体。
抽象方法没有定义,方法名后面直接跟一个分号,而不是花括号。
public abstract class Employee { private String name; private String address; private int number; //抽象方法 public abstract double computePay(); //其余代码 }
声明抽象方法会造成以下两个结果: 如果一个类包含抽象方法,那么该类必须是抽象类。 任何子类必须重写父类的抽象方法,或者声明自身为抽象类。
Java 重写(Override)与重载(Overload)
重写(Override)
重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!
//父类 class Animal{ public void move(){ System.out.println("动物可以移动"); } } //子类 class Dog extends Animal{ //重写 public void move(){ //方法里内容随意修改 System.out.println("重写成功"); System.out.println("狗可以跑和走"); } }
方法的重写规则 参数列表与被重写方法的参数列表必须完全相同。 返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类(java5 及更早版本返回类型要一样,java7 及更高版本可以不同)。 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected。 父类的成员方法只能被它的子类重写。 声明为 final 的方法不能被重写。 声明为 static 的方法不能被重写,但是能够被再次声明。 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。 子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。 重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。 构造方法不能被重写。 如果不能继承一个类,则不能重写该类的方法。
重载(Overload)
重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。
每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。
最常用的地方就是构造器的重载。
实例
public class Overloading { public int test(){ System.out.println("test1"); return 1; } public void test(int a){ System.out.println("test2"); } //以下两个参数类型顺序不同 public String test(int a,String s){ System.out.println("test3"); return "returntest3"; } public String test(String s,int a){ System.out.println("test4"); return "returntest4"; } public static void main(String[] args){ Overloading o = new Overloading(); System.out.println(o.test()); o.test(1); System.out.println(o.test(1,"test3")); System.out.println(o.test("test4",1)); } }
重载规则:
被重载的方法必须改变参数列表(参数个数或类型不一样);
被重载的方法可以改变返回类型;
被重载的方法可以改变访问修饰符;
被重载的方法可以声明新的或更广的检查异常;
方法能够在同一个类中或者在一个子类中被重载。
无法以返回值类型作为重载函数的区分标准。
Java 多态
多态是同一个行为具有多个不同表现形式或形态的能力。
多态就是同一个接口,使用不同的实例而执行不同操作
多态存在的三个必要条件
- 继承
- 重写
- 父类引用指向子类对象:Parent p = new Child();
多态的实现方式
方式一:重写
方式二:接口
方式三:抽象类和抽象方法
Java 接口
接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
/* 文件名 : Animal.java */ interface Animal { public void eat(); public void travel(); }
在实现接口的时候,也要注意一些规则:
- 一个类可以同时实现多个接口。
- 一个类只能继承一个类,但是能实现多个接口。
- 一个接口能继承另一个接口,这和类之间的继承比较相似。
接口的实现
1 // 文件名: Sports.java 2 public interface Sports 3 { 4 public void setHomeTeam(String name); 5 public void setVisitingTeam(String name); 6 } 7 8 // 文件名: Football.java 9 public interface Football extends Sports 10 { 11 public void homeTeamScored(int points); 12 public void visitingTeamScored(int points); 13 public void endOfQuarter(int quarter); 14 } 15 16 // 文件名: Hockey.java 17 public interface Hockey extends Sports 18 { 19 public void homeGoalScored(); 20 public void visitingGoalScored(); 21 public void endOfPeriod(int period); 22 public void overtimePeriod(int ot); 23 }
接口和抽象类的区别
1、定义的关键字不同。 2、子类继承或实现关键字不同。 3、类型扩展不同:抽象类是单继承,而接口是多继承。 4、方法访问控制符:抽象类无限制,只是抽象类中的抽象方法不能被 private 修饰;而接口有限制,接口默认的是 public 控制符。 5、属性方法控制符:抽象类无限制,而接口有限制,接口默认的是 public 控制符。 6、方法实现不同:抽象类中的普通方法必须有实现,抽象方法必须没有实现;而接口中普通方法不能有实现,但在 JDK 8 中的 static 和 defualt 方法必须有实现。 7、静态代码块的使用不同:抽象类可以有静态代码块,而接口不能有。