(前言)Java 和 C++ 的区别?
- 都是面向对象的语言,都支持封装、继承和多态
- Java 不提供指针来直接访问内存,程序内存更加安全
- Java 的类是单继承的,C++ 支持多重继承;虽然 Java 的类不可以多继承,但是接口可以多继承。
- Java 有自动内存管理机制,不需要程序员手动释放无用内存
- 在 C 语言中,字符串或字符数组最后都会有一个额外的字符‘\0’来表示结束。但是,Java 语言中没有结束符这一概念。 这是一个值得深度思考的问题,具体请看这篇文章。
面向对象
构造器
构造器类似于C++语言中的构造函数,
构造器的结构:
1.和类名相同
2.没有返回值
作用:
1. new 的本质是在调用构造方法
2. 初始化对象的值
注意:在定义了有参构造之后,若想使用无参构造,必须显式的定义一个无参的构造(和C++中的有参构造函数和无参构造函数基本相同)。
public class demo1 {
String name;
//无参构造
public demo1() {
}
//有参构造
public demo1(String name) {
this.name = name;
}
}
在调用构造函数时,只能通过 new 的方法调用:
类名 + 对象名 = new 类名();
如:
Student student = new Student();
student.name = xxx;
封装
封装的好处:
1.提高程序的安全性,保护数据
2.隐藏代码的实现细节
3.统一接口
4.提高系统的可维护性
封装的方法:
属性私有(private),get / set
private int age;
public static void main(String[] args) {
}
//set:设置
public int setAge(int age) {
this.age = age;
return this.age;
}
//get:读取
public int getAge() {
return this.age;
}
继承
继承的本质是对某一批类的抽象,关键字为 extends
。比如 A 类继承了 B 类,我们就写成
class A extends B(){
}
继承是子类继承父类,我们也可以理解是 “is a” 的关系,比如:旺财是一只狗,旺财相当于子类,狗相当于父类,子类继承了父类的所有属性。
Java 中类只有单继承,没有多继承! 可以这样理解:一个儿子只能有一个爸爸,而一个爸爸可以有多个儿子。
所有的类都默认继承了 Object 类,如果 A 类继承了 B 类,那么 Object 就是 A 类的祖父类。也就是说,一个类只能直接继承一个类,而可以间接继承多个类。
private 和 protected 的区别
private
和 protected
修饰的属性外界都不能直接访问,但 protected
修饰的属性其子类是可以调用的,而 private
修饰的属性除了自身任何人都访问不了:
可以通过 super
来访问父类中 protected
修饰的属性。
public class Person {
protected String name;
private int age;
public static void main(String[] args) {
}
}
public class Student extends Person{
public static void main(String[] args) {
Student stu = new Student();
System.out.println(super.name);
System.out.println(stu.age); //error
}
}
super关键字
调用父类的构造器:super();
,当调用子类的构造器时系统会默认先调用父类的构造器,如果要显式写出 super();
必须在子类构造器的第一行。
public Student() {
// super();//默认就有的,作用是调用父类的无参构造器,若要显式写出,必须写在子类构造器的第一行
// super(xxxx);//调用父类的有参构造器,必须显式写出
System.out.println("Student的无参构造");
}
当父类里面写了有参构造时,不论是父类还是子类要想调用无参构造都必须显式的写出无参构造,否则会出错。
super 注意点:
- super 调用父类的构造方法,必须写在构造方法的第一行。
- super 必须只能出现在子类的方法或者构造方法中。
- super 和 this 不能同时调用构造方法!即
super ();
和this ();
不能同时出现在一个函数中。
继承的几个要点:
- 子类拥有父类对象所有的属性和方法(包括私有属性和私有方法),但是父类中的私有属性和方法子类是无法访问,只是拥有。
- 子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
- 子类可以用自己的方式实现父类的方法。(重写)
重写
重写:需要有继承关系,子类重写父类的方法!重写是指方法重写,和属性无关!
为什么需要重写:当子类需要使用父类的一些功能,而子类需要增加新的功能,可以通过重写实现。在实际开发过程中,如果改变父类的方法,父类的所有子类也会被改写,造成麻烦,所以我们使用重写来避免这一情况。
重写的特点:
1.方法名必须相同
2.参数列表必须相同
3.修饰符:子类的访问权限必须不能比父类小 *访问权限:*public > protected > default > private
4.抛出的异常范围可以被缩小,但不能扩大
5.父类私有的方法,子类不能进行方法重写
重写:子类的方法和父类必须要一致,方法体不同!
无法重写的方法:
1. **static 方法,属于类,不属于实例**
2. **final 常量池**
3. **private 方法**
方法重写和方法重载的区别:
- 方法重写:子类和父类中方法相同,两个类之间的关系,函数的返回值类型、函数名、参数列表都一样
- 方法重载:指在同一个类中,多个方法名相同,他们的参数列表不同(个数不同,数据类型不同)
对比 this :
代表的对象不同:
this : 本身调用者这个对象
super : 代表父类对象的引用
前提:
this : 没有继承也可以使用
super : 只有在继承条件才可以使用
构造方法:
this () ; 本类的构造
super () ; 父类的构造
多态
父类的引用变量指向子类对象:
父类类型 变量名 = new 子类类型();
变量名.方法名();
Person per = new Student();
per.xxxx();
对象能执行哪些方法,主要看左边,和右边关系不大!
Person per = new Student();
Student stu = new Student();
如果要调用的方法左边的类没有,就调用失败。若子类重写了父类的方法,就调用子类重写后的方法。
上述代码中:
Student 是子类,能够调用自身或者继承父类的方法。
Person 是父类,只能够调用自身的方法,不能调用子类独有的方法。
如果父类想要调用子类的方法(父类转换成子类),以上面为例,Person 想要调用 Student 的一些独有的方法,就需要类型转换这一操作:
Person per = new Student();
((Student) per).go();
((Student) per).run();
子类如果想要转换为父类(向上转型)
父类转换为子类(向下转型):强制转换
多态成员的特点
-
成员变量在编译时,参考的是引用类型所属的类(父类)中是否有被调用的成员变量。没有则编译失败。
-
成员变量在运行时,参考的也是引用类型所属的类(父类)中是否有被调用的成员变量。没有则运行失败。
即:成员变量编译和运行都是看等号的左边(父类)
-
成员方法编译时,参考引用变量所属的类(父类),如果类中没有调用的方法,编译失败
-
成员方法运行时,参考引用变量所指的对象所属的类(子类),并运行对象所属类中的方法
即:成员方法编译看左边(父类),运行看右边(子类)//创建父类 public class Fu { int num = 1; //定义成员变量 public void fun() //定义成员方法 { System.out.println("父类"); } } //创建子类 public class Zi extends Fu { int num = 2; public void fun() { System.out.println("子类"); } } //main中调用 public class Main { public static void main(String[] args) { Fu f = new Zi(); System.out.println(f.num); //成员变量编译和运行都是参考父类的 f.fun(); //成员方法编译参考父类,运行参考子类 } }
运行结果:
1 子类
多态注意事项:
1.多态是方法的多态,属性没有多态
2.必须有父子类关系或类实现接口关系
3.存在的条件:有继承关系,方法需要重写,父类引用指向子类对象