Java入门2.1---面向对象的主线1---类及类的构成成分:属性、方法、构造器、代码块、内部类
面向对象编程的三条主线:
- 类及类的构成成分:属性 方法 构造器 代码块 内部类
- 面向对象编程的特征:封装性 继承性 多态性(抽象性)
- 其他的关键字:this super package import static final abstract interface
一、类
基本元素:类和对象
成员:
- 属性:Field=属性=成员变量:
- 方法:Method=(成员)方法=函数
面向对象思想的落地法则:
- 设计类,并设计类的成员(成员变量&成员方法)
- 通过类,来创建类的对象(也称作类的实例化)
- 通过“对象.属性”或“对象.方法”来调用,完成相应的功能
对象之间独立:创建的多个对象,彼此各自拥有一套类的属性,当对其中一个对象的属性进行修改时,不会影响搭配其他对象的属性值。
二、类的构成成分
1.属性(成员变量)
1.1 属性的声明的格式
修饰符 数据类型 变量名 = 初始化值 // java是强数据类型的语言
1.2 成员变量 VS 局部变量
相同点:
- 遵循变量声明的格式:修饰符 数据类型 变量名 = 初始化值 // java是强数据类型的语言
- 都有作用域
不同点:
成员变量 | 局部变量 | |
声明的位置 | 在类体内里,方法体外声明的变量 | 方法体内部声明的变量 |
修饰符 | public private protected 缺省 | 局部变量没有修饰符,与所在的方法修饰符相同 |
初始化值 |
如果在声明时候,不显示的赋值,那么不同数据类型会有不同的默认初始化值。
|
一定要显示的赋值(局部变量没有默认初始化值) |
内存中的存放位置 | 堆空间 |
栈空间 例:局部变量n被设置为"付昊",结束调用之后n就会从栈中清除。 |
总结:关于变量的分类
1.3 内存划分的结构
- 栈(stack):局部变量、对象的引用名、数组的引用名
- 堆(heap):new出来的“东西”(如:对象的实体,数组的实体),含成员变量
- 方法区:含字符串常量(字符串常量池)、类名
- 静态域:存放类中静态的的变量
2.方法(提供某种功能的实现)
2.1 格式
权限修饰符 (其他的关键字:static/final/abstract) 返回值类型(void:无返回值/具体的返回值) 方法名(形参列表){}
举例:
public void eat(){} public String getName(){} public void setName(String n){}
2.2 关于返回值类型
- void:表明方法不需要返回值
- 有返回值的方法,在方法的最后一定有return+返回值类型对应的变量
记忆:void与return不可以同时出现在一个方法内,像一对“冤家”
方法内可以调用本类的其他方法或属性,但是不能在方法内再定义其他方法。
2.3 方法的重载
要求:
- 同一个类中;
- 方法名必须相同;
- 方法的参数列表不同(参数的个数不同/参数类型不同)
方法的重载与方法的返回值类型没有关系:
class OverLoad{ //定义两个int型变量的和 public int getSum(int i,int j){ return i + j; } //定义三个int型变量的和 public int getSum(int i,int j,int k){ return i + j + k; } //不能与其他几个方法构成重载 //public void getSum(int i,int j,int k){ // return i + j + k; //} //定义两个double型数据的和 public double getSum(double d1,double d2){ return d1 + d2; } //定义三个double型数组的和 public double getSum(double d1,double d2,double d3){ return d1 + d2 + d3; } }
//参数类型相同,但顺序不同是允许的 public void method1(int i,String str){ } public void method1(String str,int j){ } //参数类型相同,但参数名字不同是不允许的 //public void method1(int i,String str){ //} //public void method1(int j,String str){ //}
//判断与void show(int a,char b,double c){}构成重载的有: void show(int x,char y,double z){}//no int show(int a,double c,char b){}//yes void show(int a,double c,char b){}//yes boolean show(int c,char b){}//yes void show(double c){}//yes double show(int x,char y,double z){}//no void shows(){double c;}//no
2.4 匿名类对象
创建的类的对象是匿名的。
- 当我们只需要一次调用类的对象时,我们就可以考虑使用匿名的方式创建类的对象。(栈中没有名字,堆中有类的对象)
- 特点:创建的匿名类的对象只能够调用一次。
2.5 可变个数的形参的方法
- 格式:对于方法的形参:数据类型 ... 形参名
- 可变个数的形参的方法与同名的方法之间形成重载
- 可变个数的形参在调用时,个数从0开始,到无穷多个
- 使用可变多个形参的方法与方法的形参使用数组是一致的
- 若方法中存在可变个数的形参,那么一定要**声明在方法形参的最后**
- 在一个方法中,**最多**声明一个可变个数的形参
public void sayHello(){ System.out.println("hello world"); } public void sayHello(String str1){ System.out.println("hello " + str1); } //可变个数的形参的方法,包含前两个方法,实际写的时候,可以省略前两个方法 public void sayHello(String ... args){ for(int i=0;i<args.length;i++){ System.out.println(args[i]); } } public void sayHello1(String[] args){ for (int i=0;i<args.length;i++){ System.out.println(args[i]); } } /* public int getSum(int i,int j){ return i + j; } public int getSum(int i,int j,int k){ return i + j + k; } */ public int getSum(int ... args){ int sum = 0; for(int i = 0;i < args.length;i++){ sum += args[i]; } return sum;
2.6 方法的参数(值)传递(重点、难点)
2.6.1 形参 VS 实参
- 形参:方法声明时,方法小括号内的参数
- 实参:调用方法时,实际传入的参数的值
2.6.2 参数传递机制规则
java中的参数传递机制,值传递机制
(1)形参是基本数据类型
将实参的值传递给形参的基本数据类型的变量
/* public class TestArgsTransfer{ public static void main(String[] args){ TestArgsTransfer tt = new TestArgsTransfer(); DataSwap ds = new DataSwap(); System.out.println("ds.i "+ds.i+" ds.j "+ds.j); tt.swap(ds); System.out.println("ds.i "+ds.i+" ds.j "+ds.j); } public void swap(DataSwap d){ int tmp = d.i; d.i = d.j; d.j = tmp; } } class DataSwap{ int i = 10; int j = 5; }*/ public class TestArgsTransfer{ public static void main(String[] args){ int i = 3; int j = 6; TestArgsTransfer tt = new TestArgsTransfer(); System.out.println("i "+i+" j "+j); tt.swap(i,j); System.out.println("i "+i+" j "+j);//没有交换 } public void swap(int i,int j){ int tmp = i; i = j; j = tmp; } }
(2)形参是引用数据类型的
将实参的引用类型变量的值(对应的堆空间的对象实体的首地址)传递给形参的引用类型变量
public class TestArgsTransfer{ public static void main(String[] args){ TestArgsTransfer tt = new TestArgsTransfer(); DataSwap ds = new DataSwap(); System.out.println("ds.i "+ds.i+" ds.j "+ds.j); tt.swap(ds); System.out.println("ds.i "+ds.i+" ds.j "+ds.j); } public void swap(DataSwap d){ int tmp = d.i; d.i = d.j; d.j = tmp; } } class DataSwap{ int i = 10; int j = 5; } 举例: class Value{ int i = 15; } class Test{ public static void main(String argv[]){ Test t = new Test(); t.first(); } public void first(){ int i = 5; Value v = new Value(); v.i = 25; second(v,i); System.out.println(v.i); } public void second(Value v,int i){ i = 0; v.i = 20; Value val = new Value(); v = val; System.out.println(v.i + " " + i); } } 最终结果为: 15 0 20
3.构造器(构造方法)
类的第三个成员:构造器(constructor 构造方法)
3.1 构造器的作用
- 创建对象;
- 给创建的对象的属性赋值
注意:
- 设计类时,若不显示声明类的构造器的话,程序会默认提供一个空参的构造器
- 一旦显示的定义类的构造器,那么默认的构造器就不再提供
- 如何声明类的构造器,格式:权限修饰符 类名(形参){}
- 类的多个构造器之间构成重载
public class TestPerson{ public static void main(String[] args) { Person p1 = new Person(); String str = new String("bunny"); Person p2 = new Person("aa"); } } class Person{ //属性 private String name; private int age; //构造器 public Person(String n){ name = n; } public Person(){ } public Person(int a){ age = a; } public Person(String n,int a){ name = n; age = a; } }
3.2 类对象的属性赋值的先后顺序
- 属性的默认初始化(new数据类型的默认值);
- 属性的显示初始化(定义数据类型时候的赋值);
- 初始化块;
- 通过构造器给属性初始化;(对象.setName());
- 通过”对象.方法“的方式给属性赋值
4. 初始化块(代码块)
4.1 主要作用
用来初始化类的成员变量
代码块如果有修饰的话,只能使用static;
4.2 属性赋值执行顺序
- 默认的初始化;
- 显示的初始化或代码块初始化(此处两个结构按照顺序执行);
- 构造器中;
- 通过方法对对象的相应属性进行修改。
4.3 分类:非静态代码块 VS 静态代码块
非静态代码块:没有static修饰的代码块 | 静态代码块:用static修饰的代码块 |
|
|
5.内部类
5.1 定义
在Java中,允许一个类的定义位于另一个类的内部,前者称为内部类,后者称为外部类。
- Inner class一般用在定义它的类或语句块之内,在外部引用它时必须给出完整的名称。
- Inner class的名字不能与包含它的类名相同;
- Inner class可以使用外部类的私有数据,因为它是外部类的成员,同一个类的成员之间可相互访问。而外部类要访问内部类中的成员需要:内部类.成员或者内部类对象.成员。
5.2 内部类的分类
5.2.1 成员内部类
- 声明在类内部且方法外,是外部类的一个成员
- 可以有修饰符(4个)
- 可以用static/final修饰(static成员内部类和非static成员内部类)
- 可以调用外部类的属性、方法
5.2.2 局部内部类
- 声明在类的方法里、匿名内部类
- 可以用abstract修饰
- 还可以在其内部定义属性、方法、构造器
5.2.3 重点掌握
(1)如何创建成员内部类的对象(如:创建Bird类和Dog类的对象)
- 创建静态内部类的对象,可以直接通过外部类调用静态内部类的构造器;
- 创建非静态的内部类的对象,必须先创建外部类的对象,通过外部类的对象调用内部类的构造器。
(2)如何区分调用外部类、内部类的变量(尤其是变量重名时)
(3)局部内部类的使用
常常使用一个方法,使其返回值为某个类或接口的对象。而这个类或接口在方法内部创建。
6.类初始化顺序
普通类:
- 静态变量
- 静态代码块
- 普通变量
- 普通代码块
- 构造函数
继承的子类:
- 父类静态变量
- 父类静态代码块
- 子类静态变量
- 子类静态代码块
- 父类普通变量
- 父类普通代码块
- 父类构造函数
- 子类普通变量
- 子类普通代码块
- 子类构造函数
抽象的实现子类: 接口 - 抽线类 - 实现类
- 接口静态变量
- 抽象类静态变量
- 抽象类静态代码块
- 实现类静态变量
- 实习类静态代码块
- 抽象类普通变量
- 抽象类普通代码块
- 抽象类构造函数
- 实现类普通变量
- 实现类普通代码块
- 实现类构造函数
接口注意:
- 声明的变量都是静态变量并且是final的,所以子类无法修改,并且是固定值不会因为实例而变化
- 接口中能有静态方法,不能有普通方法,普通方法需要用defalut添加默认实现
- 接口中的变量必须实例化
- 接口中没有静态代码块、普通变量、普通代码块、构造函数
参考链接: