目录
1. 类 和 对象
2. java中的数据类型
3. 内存分析
4. 方法的重载
5. 方法的重写
6. 参数的传递
值传递
引用传递
this关键字
static 关键字
代码块
package 和 import
面向对象的三(四)大特征 封装 继承 抽象 多态
1. 封装
访问修饰符
2. 继承
3. 抽象
4. 多态
final修饰符
接口
什么接口
特征
如何使用接口
接口是一种能力
接口是一种规范(约定)
接口和抽象类
接口和抽象类的区别
1. 类 和 对象
- 对象是类的具体实现,类是对象的抽象。
- 通过对象抽象出类,然后通过类再去认识对象。例如:天使的案例。
2. java中的数据类型
- 基本数据类型 4类 8种 整数(byte short int long) 浮点(float double) 布尔(boolean)字符(char)
- 引用数据类型 类,接口,数组
3. 内存分析
- 栈:stake
– 存放:局部变量
– 先迚后出,自下而上存储
– 斱法执行完毕,自动释放空间
- 堆:heap
– 存放new出来的对象
– 需要垃圾回收器来回收:System.gc()
- 方法区:
– 存放:类的信息(代码)、 static变量、字符串常量等
4. 方法的重载
在同一个类中。方法参数列表不一样(个数,类型,顺序)
一般构造方法都需要重载。
5. 方法的重写
6. 参数的传递
值传递
只是将值传递。基本数据类型都是值传递。
package com.mark.java.base;
public class Demo2 {
public static void main(String[] args) {
int a = 1;
Demo2 demo2 = new Demo2();
demo2.te(a);
System.out.println(a);
}
public void te(int b){
b=10;
}
}
执行结果:
1
分析:
1. 变量a指向1。
2. 调用te(int b)方法时,将a的值赋值个b,此时b指向1.
3.b=10;此时b指向10;
4. 输出a,此时a还是指向1,并没有发生变化。
引用传递
将引用变量的地址进行传递,两个变量名指向同一个地址,指向同一个对象。所以当操作其中一个变量时,相当于指向的对象发生变化
场景1
package com.mark.java.base;
public class Demo {
public static void main(String[] args) {
App app = new App();
app.age=10;
new Demo().aa(app);
System.out.println(app.age);
}
public void aa(App a){
a.age = 9999;
}
}
运行结果:
9999
分析:
1. 在调用方法aa()时,将引用变量app传入变量a,传递的时地址。到目前为止,app 和 a的地址是相同的,都指向new App()对象,假设叫 A对象。
2. 当a发生变化时,相当于操作了A对象。
3. app也也指向A对象,当输出app.age时,就输出了A对象的age值。为9999
场景2
package com.mark.java.base;
public class Demo {
public static void main(String[] args) {
App app = new App();
app.age=10;
App app1 = new App();
app1.age = 20;
new Demo().change(app,app1);
System.out.println(app.age);
System.out.println(app1.age);
}
public void aa(App a){
a.age = 9999;
}
public void change(App x,App y){
App temp = x;
x = y;
y = temp;
System.out.println(x.age);
System.out.println(y.age);
}
}
运行结果:
20
10
10
20
分析,这个比较复杂一点。
1. 目前有个5个变量, 变量app ,变量app1 ,变量x, 变量y ,变量temp
2. 变量app指向new App(),假设为A对象,变量app1指向new App() ,假设为B对象,调用方法时change(App x,App y),a-->x, b-->y, 此时x指向A对象,y指向B对象。
3. 在方法中,x-->temp, y--x, temp-->y。这里相当于将a--->y,将b--->x, 也就是说此时y指向A对象,x指向B对象,所以输出x.age 和 y.age是 20 和10;
4.当执行完方法后,app还是指向A对象,app1还是B对象,所以 app.age 为10,app1.age 为20;没有发生任何改变。
场景3
package com.mark.java.base;
public class Demo {
public static void main(String[] args) {
App app = new App();
app.age=10;
App app1 = new App();
app1.age = 20;
new Demo().change(app,app1);
System.out.println(app.age);
System.out.println(app1.age);
}
public void aa(App a){
a.age = 9999;
}
public void change(App x,App y){
App temp = x;
x = y;
y = temp;
y.age = 111111;
System.out.println(x.age);
System.out.println(y.age);
}
}
执行结果:
20
111111
111111
20
分析,这个比较复杂一点。
1. 目前有个5个变量, 变量app ,变量app1 ,变量x, 变量y ,变量temp
2. 变量app指向new App(),假设为A对象,变量app1指向new App() ,假设为B对象,调用方法时change(App x,App y),a-->x, b-->y, 此时x指向A对象,y指向B对象。
3. 在方法中,x-->temp, y--x, temp-->y。这里相当于将a--->y,将b--->x, 也就是说此时y指向A对象,x指向B对象,然后对y进行操作,相当于对对象A操作, 所以输出x.age 和 y.age是 20 和1111;
4.当执行完方法后,app还是指向A对象,app1还是B对象,但是A对象已经发生变化,所以 app.age 为1111,app1.age 为20;
this关键字
this 表示当前对象的指针。指向当前对象,表示当前对象的引用。一定要理解当前对象。
Person person1 = new Person(); 假设为对象A, person1 是对象A的引用变量,person1存放在栈中,对象A在堆中,person1指向对象A。
Person person2 = new Person(); 假设为对象B, person2 是对象B的引用变量,person2存放在栈中,对象B在堆中,person2指向对象B。
而this 和person1 、 person2是不一样的。this不存在栈中,this存在是堆里对象里。堆里的每个对象里都有this。对象A中有,对象B中也有。对于对象A来时说this指的当前对象指的就是对象A。同理对于对象B来说,this指的时B对象。
this的用法
- 构造方法中
1. 区分参数变量和成员变量
2. 调用其他的构造方法
需要注意两点。
(1)this.Demo3(。。)这种写法时严格禁止的。直接写this(..)
(2)当在一个构造方法中调用另一个构造方法时,必须放在方法体的第一行。
错误的表示
public Demo3(String name){
System.out.println(name);
this(name,0);
}
正确的表示
public Demo3(String name){
this(name,0);
System.out.println(name);
}
- 普通方法中
1. 调用该类中其他的方法
2. 区分参数变量和成员变量
package com.mark.java.base;
public class Demo3 {
private String name;
private int age;
public Demo3(){
}
/**
* this用来区分参数变量和成员变量
* @param name
* @param age
*/
public Demo3(String name,int age){
this.name = name;
this.age = age;
}
/**
* 调用其他的构造方法,不能写为this.Demo3(..),可以省略方法名称
* @param name
*/
public Demo3(String name){
this(name,0);
}
/**
* this用来区分参数变量和成员变量
* @param name
*/
public void app(String name){
System.out.println(name);
System.out.println(this.name);
}
/**
* 调用其他的方法
*/
public void appOne(){
this.app("zhangsan");
}
}
static 关键字
1. 静态变量
- 在对象创建的时候就被初始化。
- 静态变量被所有的对象共享,属于公共变量,类和对象都可以进行调用。
- 成员变量属于对象,放在堆中,而静态变量属于类,放在方法区的静态区。
- 静态变量不能定义在普通方法中,也不能不定义在静态方法中。为什么,静态变量和静态方法都是属于类的,但是如果静态变量在方法中,属于该方法的局部变量,没法属于类变量,相互矛盾,所欲时不行的。
- 类调用和对象调用时时共享的。
2. 静态方法
- 不需要对象,可以通过类直接调用。对象也可以。
- 非静态方法中也可以调用静态方法。因为也数据对象,共享的。
- 静态方法中不能够调用非静态方法。非静态方法属于对象,必须有对象调用。
- 静态方法中不能使用this super等关键字。因为this是指向对象的,意味着必须有对象才能有this,而静态方法时属于类的,再类加载的时候就有了,但此时还没有对象
代码块
- 普通代码块:定义在方法中,使用{}括起来代码块叫做普通代码块
- 构造代码块:定义在类中,使用{}括起来代码块叫做构造代码块。必须创建对象时才执行。
注意:构造代码块在编译后会加在所有的构造方法里。且为第一个执行。但是如果在构造方法中调用另一个构造方法的话,这个构造方法前不加入该代码块。因为不能够违反构造方法中调用构造方法,该语句必须在第一行的原则。
- 静态代码块,用static{}括住的代码叫做静态代码块,在类加载时优先执行。
- 同步代码块
package com.mark.java.base;
public class Demo4 {
{
System.out.println("构造代码块");
}
public void app(){
System.out.println("app");
{
System.out.println("普通代码块");
}
}
static{
System.out.println("静态代码块");
}
public static void main(String[] args) {
Demo4 demo4 = new Demo4();
demo4.app();
}
}
package 和 import
package 作用
- 解决类的重名问题
- 管理类,将合理的类放在合理的包下
- 例如 package com.tzw.util
import
例如Date 类
如果不导包 , java.util.Date date = new java.util.Date();
如果导包, Date date = new Date();
导包 import java.Util.Date 或者 import java.Util.*
静态导入
import static
例如 : import static java.lang.Math.* 导入Math类中的所有静态属性或者方法。
或者具体的 import static java.lang.Math.abs;
package com.mark.java.base;
import static java.lang.Math.abs;
public class Demo5 {
public static void main(String[] args) {
System.out.println(Math.abs(-5));
System.out.println(abs(-8));
}
}
package com.mark.java.base;
import static java.lang.Math.abs;
public class Demo5 {
public static void main(String[] args) {
System.out.println(Math.abs(-5));
System.out.println(abs(-8));
}
}
面向对象的三(四)大特征 封装 继承 抽象 多态
1. 封装
- 什么封装,将类的某些信息隐藏在类的内部,不允许外部直接访问,而是通过该类提供的方法来实现对隐藏信息的操作。
- 为什么要封装,隐藏内部的细节,通过提供的方法进行访问,提高系统的扩展性和课维护性,便于修改。高内聚,低耦合。
高内聚, 就是类内部的操作自己完成,不允许外部干预。
低耦合,暴露少量的方法给外部使用
- 怎么实现封装。通过访问修饰符。1.属性用private修饰 2. 通过public的get set方法进行属性的操作 3. 在get set方法中可以增加逻辑。
访问修饰符
- 成语变量和成员方法上的访问修饰符
private
default
protected,可以通过子类的对象进行方法,即使和子类不在同一个包下。
public
注意:那么构造方法可以用除了public之外的修饰符么?答案是可以的。但是不能有default 的写法。
public Demo(){
}
protected Demo(String a){
}
private Demo(String a,String b){
}
- 类上的访问修饰符
public 所有类可以访问。
default 同一个包下可以访问。
2. 继承
- java是单继承。
- 子类继承父类的所有的非私有的属性和方法。依旧无法违反 访问修饰符的限制。
- super 关键字
1. 可以使用super调用父类中被子类覆盖的属性和方法。
2. 当在子类的构造方法中调用父类的构造方法时,必须放在第一个。
3. 子类构造方法必定会隐式的调用父类的构造方法super(),当然也可以手动指定调用哪个父类的构造方法。换句话时在创建子类对象时一定会优先创建父类对象。
4. 子类构造方法中this(),super() 不能够够同时使用,因为this 和 super关键字都要求顺序,必须第一个,所以不能够同时使用。
5. java虽然是单继承的,但是可以进行多重继承。a继承b,b继承c这样。
多重继承的初始化顺序, 父类属性---》父类构造方法------》子类属性----》子类构造方法。为什么属性会比构造方法早呢,举个例子,对于有参数的构造方法,在构造方法调用的时候就可以使用属性了。
- 方法的重写
1. 存在继承关系,当父类的方法不满足子类的需求时,子类可以重写父类的方法。
2. 重写后会先调用重写后的方法。
3. 重写
(1) 子类重写方法 访问修饰符访问权限不能比父类小
(2)子类重写方法 返回值必须和父类的返回值一致或是其子类。
(3)子类重写方法,方法名称和参数列表必须和父类一致。
4. 静态方法
静态方法可以继承,子类能够调用,但是不能够算重写。虽然可以自子类定义,但是不算是方法的重写。
3. 抽象
有人把抽象也算做事java的三大特征。
某些情况下类实例化并没有什么具体意义,就可以将自类设置成抽象类。
- 抽象类用abstract 关键字修饰。抽象类时不能够实例化的。
- 抽象类中如果有抽象方法(用abstract修饰的方法),抽象方法是不能有方法体的,需要子类继承去实现抽象方法。
- 抽象类不一定有抽象方法,有抽象方法的类一定是抽象类。
- 抽象类可以有构造方法,一般抽象类的构造方法是让子类去调用的。
4. 多态
1 通俗的将什么是多态
就是不同的对象对于同一指令(调用相同名称的方法)有不用的反应(不用的方法体)。
2. 多态的前提或者规则
- 存在继承关系或者实现接口关系
- 子类重写了父类的方法,或者实现类实现了接口
- 父类引用指向子类对象,或者接口引用指向具体的实现类对象
3. 多态的应用场景
- 使用父类作为方法的参数传递
- 使用父类当作方法的返回值
4. 引用变量的两种类型
编译时类型,是声明时的类型决定,声明的是什么类型就是什么类型 ,一般是父类或者接口
运行时类型,具体是哪个子类就是哪个子类的类型。
5. 类型的转换
自动转换,也叫向上转型,由子类转为父类。
强制转换,也叫向下转型,有父类转为子类。结合 instanceof 关键子。 对象 instanceof 类或者接口
这里可以理解,子类对象即使子类类型也是父类类型。而父类只是父类对象。
final修饰符
- 修饰变量, 表示变量的值不可改变
- 修饰方法,表示方法不能被重写
- 修饰类,表示类不能被继承
接口
面向接口编程
什么接口
1. interface
2.接口中的方法不能有方法体
3. 子类implement接口
特征
1. interface
2.接口中的方法和变量的访问修饰符必须是public。
3. 接口中变量是静态常量,用public static final 修饰,例如: public static final int a =1; 可以省略,省略后为int a=1,此时并不表示是默认的访问修饰符。在编译的时候会自动加上 public static final;
4. 接口中的方法都是抽象方法,子类必须实现所有的方法。方法必须用public 修饰,也可以省略,此时并不表示是默认的访问修饰符。
5. 子类可以同时实现多个接口
6.接口不能实例化。不能有构造方法。
如何使用接口
接口是一种能力
面向接口编程,只关心能力而不关心具体的实现。
接口是一种规范(约定)
体现在方法名称和注释上
面向接口的约定而不关心具体的实现。
接口和抽象类
1. 通俗的讲 接口是比抽象类更抽象的 抽象类。
2. 什么时候用抽象类,什么时候用接口
抽象类 是用来被继承的,和子类之间是 is a的关系。
接口是用来实现的,子类实现接口,子类就拥有了接口的能力或者必须遵守接口的约定,是has a的关系。
接口和抽象类的区别