1.参数传递的方式
值传递
在参数传递过程中,形参和实参占用了两个完全不同的内存空间。形参所存储的内容是实参存储内容的一份拷贝。
引用传递
在参数传递的过程中,形参和实参完全是同一块内存空间,两者不分彼此。
在Java中,不存在按引用调用,因为在参数传递过程中,不管传递的是基本数据类型的变量,还是对象的引用,其实都是传递的一个副本。
对象传递是引用传递,原始类型数据传递是值传递
-
在Java中对象作为参数传递时,是把对象在内存中的地址拷贝了一份传给了参数。
-
String类是个特殊的类,对它的一些操作符是重载的,如:
-
String str = “Hello”; 等价于String str = new String(“Hello”);
2.super的使用
1.子类方法中调用父类的构造方法
2.子类重写了父类的变量,子类方法要调用父类的变量必须要用super
3.调用父类被子类重写的方法;
调用父类被子类重定义的字段(被隐藏的成员变量);
4.父类中定义了一个有参的构造方法,子类中不能省略super(参数);因为默认是调用无参的构造方法。
在子类的构造方法中,只要里面没有显示的通过super去调用父类相应的构造方法,默认都是调用super(),即无参构造方法,因此要确保父类有相应的构造方法。
3.多态
多态是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。
多态就是不同对象同一方法的不同表现效果,一个行为(方法)在不同对象上的多种表现形式
多态弥补了java单继承上的不足
对象的多态性:父子类对象的转换
向上转型:子类对象变为父类对象,语法: 父类 父类对象 = 子类实例, 自动;
向下转型:父类对象变为子类对象,语法: 子类 子类对象 = (子类)父类实例,强制。
子类转型成父类后,只能访问父类的方法和属性,要想使用自己的方法,必须向下转型转回来。若子类重写了父类的方法,在调用这些方法时会对应子类相应的方法的。(动态连接,动态调用)
多态存在的三个必要条件
- 继承
- 重写
- 父类引用指向子类对象
实现多态有三个必要条件
- 继承
- 重写
- 向上转型
实现多态的两种形式
- 继承
- 接口
注意:
①使用父类类型的引用指向子类的对象;
②该引用只能调用父类中定义的方法,不能调用子类中独有的方法;
③如果子类中重写了父类中的一个方法,那么在调用该方法的时候,将会调用子类中的这个方法;
④在多态中,子类可以调用父类中的所有方法;
⑤多态主要体现为方法重载和方法重写,相同的行为,不同的实现方式;
⑥多态的主要应用是多态参数和多态集合
⑦如果一个方法中有父类作为参数类型,就意味着可以给该方法传递任何一个子类对象。
4.抽象类
抽象类的意义:
父类有多个子类时,不同子类会有相同的方法,而对方法的实现不同,抽象出父类的方法,子类要调用时,可以根据自己的情况对父类的抽象方法进行重写,这样不同子类的相同方法互不干扰,这样更有利于代码和程序的维护 。
- 抽象方法一定存在抽象类中
- 抽象类不允许创建对象,有时不允许特定类创建对象时,可以使用abstract修饰此类
- 抽象类中的方法要被使用,必须通过子类重写父类的方法,通过创建子类对象访问。
- 如果我们要访问父类的方法,可以将子类对象进行向上转型后,再调用父类方法
- 由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。
public class abstractk{
public static void main(String[] args){
B b = new B();
b.show();//要调用抽象方法,必须创建一个子类对象,进行调用
b.cry();
b.eat();
A a = (A)b;//强制转型后不能将对象赋给自身
a.run();//将b强制转型后,调用原抽象父类中的方法
}
}
abstract class A{
//抽象方法一定存在于抽象类中
abstract void show();//在父类A中声明了一个抽象类
abstract void eat();
abstract void cry();
void run(){
System.out.println("跑步");
}
}
class B extends A{
void show(){
System.out.println("重写父类抽象方法");
}
void eat() {
System.out.println("重写全部的父类抽象方法");
}
void cry() {
System.out.println("重写全部的父类抽象方法1");
}
}
子类可以是抽象类,也可以不是抽象类; 子类如果不是抽象类,必须全部重写父类的抽象方法,一个都不能少。 抽象类里的方法要么由子类全部实现,要么子类继续抽象下去。
-
抽象类可以不包括抽象方法,它反正不会去实例化,里面的方法是不是抽象的没有本质影响。
-
但是含有抽象方法的类绝不能被实例化,否则执行这个方法的时候,怎么办?
-
如果子类是非抽象的,那么它就必须实现父类中的抽象方法;否则,它继承来的抽象方法仍然没有方法体,也是个抽象方法,此时就与“**含有抽象方法的类必须是抽象类”**相矛盾了。
-
抽象类的函数可以是static,只不过不能既是abstract又是static的,因为抽象方法就是用来让子类重写的,如果加上static就变成类方法了,违背了面向对象的思想。
-
抽象类其实是可以被实例化的,但是它的实例化方式并不是通过普通的new方式来创建对象,而是通过父类的应用来指向子类的实例间接地实现父类的实例化,因为子类在实例化之前,一定会先实例化它的父类。这样创建了继承抽象类的子类对象,也就把其父类(抽象类)给实例化了。
public class B extends A{ public B(){ super();//系统默认会调用可以不用写 System.out.println("我是子类"); } public static void main(String[] args) { A a = new B();//在实例化子类时,默认先调用父类的构造函数,在调用子类的构造函数。 } } abstract class A{ public A(){//构造方法在类被实例化时自动调用 System.out.println("我是父类"); } }
5.接口
Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。我们对接口的理解,不能独立于其实现的类,接口应该说是实现类的一部分,对实现类实例化对象的方法调用可以看做对接口方法的实现,接口和实现类有种连接关系,就像一个发电站,给不同实现类所需的能量,而实现类用这个电去做什么,就要看具体用在什么地方了。
接口是实现多继承的原因,接口完全支持多继承。和类的继承类似,子接口扩展某个父接口,将会获得父接口中所定义的一切。
接口是设计(需要什么我去设计什么)的结果 ,抽象类是重构(覆盖、重写)的结果
在类加载程序运行时父类的引用指向了子类的实例化对象,就行成了多态, 但是由于java中的只能是单继承,所以担任就交给了接口。
接口就是规范,定义的是一组规则,面向对象的精髓,是对对象的抽象,最能体现这一点的就是接口。为什么我们讨论设计模式都只针对具备了抽象能力的语言(比如C++、Java、C#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。
声明格式:
[访问修饰符] interface 接口名 [extends 父接口1,父接口2…] {
常量定义;
方法定义;
}
定义接口的详细说明:
1. 访问修饰符:只能是public或默认。
2. 接口名:和类名采用相同命名机制。
3. extends:接口可以多继承。
4. 常量:接口中的属性只能是常量,总是:public static final 修饰。不写也是。
5. 方法:接口中的方法只能是:public abstract。 省略的话,也是public abstract。
要点
1. 子类通过implements来实现接口中的规范。
2. 接口不能创建实例,但是可用于声明引用变量类型。
3. 一个类实现了接口,必须实现接口中所有的方法,并且这些方法只能是public的。
4. JDK1.7之前,接口中只能包含静态常量、抽象方法,不能有普通属性、构造方法、普通方法。
- JDK1.8后,接口中包含普通的静态方法。
所以接口严格的来讲属于一个特殊的类,而这个类里面只有抽象方法和全局常量,就连构造方法也没有。
注意:通过面向接口编程,而不是面向实现类编程,可以大大降低程序模块间的耦合性,提高整个系统的可扩展性和和可维护性。
public class M implements A{
@Override
public void run(){//重写接口的所有抽象方法
System.out.println("123"+" "+age);
}
public static void main(String[] args){
interface111 K = new interface111();
K.run();
test t = new test();
t.f();
t.k();
}
}
interface A {
int age = 18;//接口中成员变量默认是public static final
String name = "gzay";
void run();//方法默认是public abstract
}
abstract class B{
int ans;
public B() {//抽象类的构造函数用来初始化抽象类的一些字段
//构造方法不可继承,但是可以供子类用super()或者super(参数,参数,...)调用
System.out.println("64165156");
}
}
class test extends B{
public void f(){
System.out.println("32165165");
}
public void k(){
System.out.println("dh");
f();//同一类的普通方法可以直接调用
}
}
1、接口可以继承接口,抽象类不可以继承接口,但可以实现接口。
2、抽象类可以继承实体类。抽象类可以实现(implements)接口,抽象类是否可继承实体类,但前提是实体类必须有明确的构造函数。
3.抽象类可以继承实体类,就是因为抽象类的可以继承性和有方法。
4、一个接口可以继承多个接口. interface C extends A, B {}是可以的. 一个类可以实现多个接口: class D implements A,B,C{} 但是一个类只能继承一个类,不能继承多个类 class B extends A{} 在继承类的同时,也可以继承接口: class E extends D implements A,B,C{} 这也正是选择用接口而不是抽象类的原因。
5.Java接口可以向上转型,任何父类可以出现的地方,子类一定可以出现,任何接口可以出现的地方,其实现类一定可以出现。
6.子类在重写接口的抽象方法时,一定要注意给重写的方法加上public,除非给接口中的抽象方法显示加上public,不然会报错。