面向对象三大特性?
面向对象的三大特性包括:封装、继承、多态。
- 封装
封装是给对象提供了隐藏内部属性和行为的能力。通过public,protected,private修饰符来给其他的位于同一个包或者不同包下面对象赋予了不同的访问权限。它可以通过隐藏对象的属性来保护对象内部的状态,并且可以防止对象之间的不良交互,提高安全性。
// 对成员变量设置私有访问权限,对信息进行隐藏
// 为每个成员变量提供对外公共方法访问(getter/setter)
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中使用extends和implements实现继承,
// 动物类(父类)
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 class Penguin extends Animal {
public Penguin(String myName, int myid) {
super(myName, myid);
}
}
- 多态
多态是同一个行为具有多个不同表现形式或形态的能力。多态就是同一个接口,使用不同的对象而执行不同操作。多态分为编译时多态和运行时多态:编译时多态指方法的重载;运行时多态指程序中定义的对象引用所指向的具体类型在运行期间才确定。运行时多态的三个必要条件:(1)继承(2)重写(3)父类引用指向子类对象。多态可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。
abstract class Animal {
abstract void eat();
}
class Cat extends Animal {
public void eat() {
System.out.println("吃鱼");
}
public void work() {
System.out.println("抓老鼠");
}
}
public static void main(String[] args) {
Animal a = new Cat(); // 向上转型
a.eat(); // 调用的是 Cat 的 eat
}
重写与重载的区别?
方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。
重写(overriding) | 重载(overloading) | |
---|---|---|
定义 | 子类根据需要定义新特性,可对父类的方法进行扩展 | 让类以统一的方式处理不同类型参数的一种手段,通过传递参数的个数和类型选择具体调用哪种方法 |
范围 | 继承类 | 同一类 |
区别 | 方法名称、返回值、参数等均相同 | 方法名称相同,参数列表不同(每个重载方法都有独一无二的参数列表) |
对this和super的认识?
this:就是类中指向对象本身的一个特殊引用。
super:向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类。
谈谈权限修饰符的特性?
权限修饰符 | 特点 | 本类 | 子类 | 同包类 | 其他类 |
---|---|---|---|---|---|
public | 公共访问 | √ | √ | √ | √ |
protected | 保护(继承+包)访问 | √ | √ | √ | × |
protected | 私有(无法)访问 | √ | × | × | × |
对java多态的理解 /Java中实现多态的机制是什么?
- 多态是什么?
多态是同一个行为具有多个不同表现形式或形态的能力。多态就是同一个接口,使用不同的对象而执行不同操作。 - 多态分类?
本质上多态分为两种:
- 编译时多态(静态绑定),如重载方法。
- 运行时多态(动态绑定),如重写方法。
编译时多态即在程序执行前方法已经被绑定,发生在编译阶段,由编译器实现,绑定的是类信息。java中的方法,只有final,static,private,重载方法和构造方法是静态绑定;所有的变量都是静态绑定。
运行时多态时编译时不确定具体调用哪个具体方法,直到运行时,根据传入的对象信息,才进行绑定相应的方法。发生在运行阶段,绑定的是对象信息。运行时多态通常有两种实现方法:1、子类继承父类(extends)2、类实现接口(implements)。使用多态应该遵循的原则是:声明和定义方法参数时总是优先使用父类类型或接口类型,创建的是实际类型。这样做可以减少代码的耦合,提高代码的可维护性。
运行时多态的必要条件有:继承、重写、父类引用指向子类对象。
- 多态动态绑定机制?
类对象方法的调用必须在运行过程中采用动态绑定机制。动态绑定的解题思路:
首先,根据对象的声明类型(对象引用的类型)找到“合适”的方法。具体步骤如下:
- 编译器检查对象的声明类型和方法名称(p.method())
若p的声明类型为Child类,则编译器会列举出Child类中所有名为method方法和父类继承的method方法,如果子类重写父类方法,则被覆盖;
若p的声明类型为Parent类,并指向子类对象,则编译器会列举出Parent类中所有名为method方法,如果子类重写父类方法,则被覆盖; - 如果能在声明类型中匹配到方法签名完全一样(参数类型一致)的方法,那么这个方法是最合适的。
- 在上一条不能满足的情况下,寻找可以“凑合”的方法。标准就是通过将参数类型进行自动转型之后再进行匹配。
自动转型会匹配最精确的一个参数列表,当一个方法可以接受传递给另一个方法的任何参数,则第二个方法比第一个方法更加精确。
- 如果仍然在声明类型中找不到“合适”的方法,则编译阶段就无法通过。
class A {
public String show(D obj){
// 方法一
return ("A and D");
}
public String show(A obj){
// 方法二
return ("A and A");
}
}
class B extends A{
public String show(B obj){
// 方法三
return ("B and B");
}
public String show(A obj){
// 方法四
return ("B and A");
}
}
class C extends B{
}
class D extends
B{
}
public class JavaStudy {
public static void main(String[] args) {
A a1 = new A(); // 创建A类对象,故a1拥有调用方法一和方法二的能力
A a2 = new B(); // 创建A类引用,指向B类对象,故a2拥有调用方法一和方法四的能力;但向上转型不能调用子类中有而父类中没有的方法,故不能调用方法三
B b = new B(); // 创建B类对象(继承A),方法四重写方法二,故b拥有调用方法一、方法三和方法四的能力
C c = new C();
D d = new D();
System.out.println("1--" + a1.show(b)); // 1--A and A 调用方法一
System.out.println("2--" + a1.show(c)); // 2--A and A 调用方法一
System.out.println("3--" + a1.show(d)); // 3--A and D 调用方法二
System.out.println("4--" + a2.show(b)); // 4--B and A 调用方法四
System.out.println("5--" + a2.show(c)); // 5--B and A 调用方法四
System.out.println("6--" + a2.show(d)); // 6--A and D 调用方法一
System.out.println("7--" + b.show(b)); // 7--B and B 调用方法三
System.out.println("8--" + b.show(c)); // 8--B and B 调用方法三
System.out.println("9--" + b.show(d)); // 9--A and D 调用方法一
}
静态属性和静态方法能被继承吗?静态方法又是否能被重写呢?
静态属性、静态方法和非静态的属性都可以被继承和隐藏而不能被重写,因此不能实现多态,不能实现父类的引用可以指向不同子类的对象。
非静态方法可以被继承和重写,因此可以实现多态。
例子:
class A { //父类
public static String staticStr = "A静态属性";
public String nonStaticStr = "A非静态属性";
public static void staticMethod(){
System.out.println("A静态方法");
}
public void nonStaticMethod(){
System.out.println("A非静态方法");
}
}
class B extends A{//子类B
public static String staticStr = "B改写后的静态属性";
public String nonStaticStr = "B改写后的非静态属性";
public static void staticMethod(){
System.out.println("B改写后的静态方法");
}
public void nonStaticMethod(){
System.out.println("B改写后的非静态方法");
}
public class JavaStudy {
public static void main(String[] args) {
A a = new B();
B b = new B();
System.out.println(a.nonStaticStr); // A非静态属性
System.out.println(a.staticStr); // A静态属性
a.staticMethod(); // A静态方法
a.nonStaticMethod(); // B改写后的非静态方法
System.out.println(b.nonStaticStr); // B改写后的非静态属性
System.out.println(b.staticStr); // B改写后的静态属性
b.staticMethod(); // B改写后的静态方法
b.nonStaticMethod(); // B改写后的非静态方法
}
}