目录
三、类的结构之三:构造器 (构造方法)constructor
一、类的结构之一:属性 field
类的设计中,两个重要结构之一:属性
对比:属性 vs 局部变量
1.相同点:
* 1.1 定义变量的格式:数据类型 变量名 = 变量值
* 1.2 先声明,后使用
* 1.3 变量都有其对应的作用域
2.不同点:
2.1 在类中声明的位置的不同
* 属性:直接定义在类的一对{}内
* 局部变量:声明在类的结构内(方法内、方法形参、代码块内、构造器形参、构造器内部)的变量
*
* 2.2 关于权限修饰符的不同
* 属性:可以在声明属性时,指明其权限,使用权限修饰符。
* 常用的权限修饰符:private、public、缺省、protected --->封装性,形容可见性
* 目前,大家声明属性时,都使用缺省就可以了。
* 局部变量:不可以使用权限修饰符。
*
* 2.3 默认初始化值的情况:
* 属性:类的属性,根据其类型,都默认初始化值。
* 整型(byte、short、int、long:0)
* 浮点型(float、double:0.0)
* 字符型(char:0 (或'\u0000'))
* 布尔型(boolean:false)
*
* 引用数据类型(类(包含字符串String)、数组、接口:null)
*
* 局部变量:没默认初始化值。
* 意味着,我们在调用局部变量之前,一定要显式赋值。
* 特别地:形参在调用时,我们赋值即可。
*
* 2.4 在内存中加载的位置:
* 属性:加载到堆空间中 (非static,static在方法池中)
* 局部变量:加载到栈空间
补充:回顾变量的分类:
方式一:按照数据类型: 基本数据类型 VS 引用数据类型
方式二:按照在类中声明的位置: 成员变量(属性)VS 局部变量
3.属性赋值方法和顺序:1 -> 2 -> 3 -> 4 (存疑)
1.默认初始化
2.显示初始化
3.构造器中赋值
4.对象.方法 或 对象.属性 赋值
二、类的结构之二:方法 method
类的设计中,两个重要结构之二:方法 描述类应该具有的功能
* 比如:Math类:sqrt()\random() \...
* Scanner类:nextXxx() ...
* Arrays类:sort() \ binarySearch() \ toString() \ equals() \ ...
* 1.举例:
* public void eat(){}
* public void sleep(int hour){}
* public String getName(){}
* public String getNation(String nation){}
* 2. 方法的声明:权限修饰符 返回值类型 方法名(形参列表){
* 方法体
* }
* 注意:static、final、abstract 来修饰的方法,后面再讲。
方法的调用:结构体名.方法名(形参列表) 记得加()
Person1 p1 = new Person1();
p1.setAge(30);
System.out.println("年龄:"+p1.getAge());//用的方法
* 3. 说明:
* 3.1 关于权限修饰符:默认方法先都使用public
* Java规定的4种权限修饰符:private、public、缺省、protected -->封装性再细说
*
* 3.2 返回值类型: 返回值 vs 没返回值
* ① 方法有返回值,则必须在方法声明时,指定返回值的类型。 同时,在方法中,使用 return关键字来返回指定类型的变量或常量:“return 数据”。
* ② 方法没返回值,则方法声明时,使用void来表示。不使用return 或 用 return;表示结束此方法。
* 我们定义方法该不该返回值?① 题目要求 ② 凭经验:具体问题具体分析
*
* 3.3 方法名:属于标识符,遵循标识符的规则和规范,“见名知意”
*
* 3.4 形参列表: 方法可以声明0个,1个,或多个形参。
* 3.4.1 格式:数据类型1 形参1, 数据类型2 形参2,...
* 3.4.2 我们定义方法时,该不该定义形参?
* ① 题目要求
* ② 凭经验:具体问题具体分析
*
* 3.5 方法体:方法功能的体现。
4. 方法的使用中,可以调用当前类的属性或方法
* 特殊的:方法A中又调用了方法A:递归方法。
* 方法中,不可以定义方法。
三、类的结构之三:构造器 (构造方法)constructor
1.构造器(或构造方法):Constructor,任何一个类都有构造器
构造器的作用:
* 1.创建类的对象 new + 构造器 eg: Person p1 = new Person();
如果不加()即new Person创建类
* 2.初始化对象的信息
2.使用说明:
* 1.如果没显式的定义类的构造器的话,则系统默认提供一个空参的构造器
* 2.定义构造器的格式:权限修饰符 类名(形参列表){}
* 3.一个类中定义的多个构造器,彼此构成重载
* 4.一旦我们显式的定义了类的构造器之后,系统就不再提供默认的空参构造器
* 5.一个类中,至少会有一个构造器。
3.JavaBean:满足以下条件的java类
- 类是public的。
- 一个无参的public的构造器。
- 属性和对应的set方法/get方法
4.举例:
public class PersonTest {
public static void main(String[] args){
//创建类的对象:new + 构造器
Person1 p1 = new Person1(); //没显式的定义类的构造器的话,则系统默认提供一个空参的构造器
p1.setAge(30); //用的方法
System.out.println("年龄:"+p1.getAge());
//构造器可以重载, 显示定义后不提供默认空参构造器
Person p2 = new Person();
System.out.println("年龄:"+p2.name+"年龄:"+p2.age);
Person p3 = new Person("Tom");
System.out.println("年龄:"+p3.name+"年龄:"+p3.age);
Person p4 = new Person("mark",30);
System.out.println("年龄:"+p4.name+"年龄:"+p4.age);
}
}
class Person{
//属性
String name;
int age;
//构造器
public Person(){
System.out.println("2构造器");
}
//构造器有形参
public Person(String n){
name = n;
}
//构造器有多个形参
public Person(String n,int m){
name = n;
age = m;
}
}
class Person1 {
private int age; //体现封装性
public void setAge(int n){
if(n>0 && n<130)
age = n;
else{
age = 0;
throw new RuntimeException("传入数据非法");
}
}
public int getAge(){
return age;
}
}
四、类的结构之四:代码块(初始化块)
1.代码块的作用:用来初始化类、对象的信息, {内容} 或 static{内容}
2.分类:代码块要是使用修饰符,只能使用static
分类:静态代码块 vs 非静态代码块
3.静态代码块:
>内部可以输出语句
>随着类的加载而执行,而且只执行一次
>作用:初始化类的信息
>如果一个类中定义了多个静态代码块,则按照声明的先后顺序执行
>静态代码块的执行要优先于非静态代码块的执行
>静态代码块内只能调用静态的属性、静态的方法,不能调用非静态的结构
非静态代码块:
>内部可以输出语句
>随着对象的创建而执行
>每创建一个对象,就执行一次非静态代码块
>作用:可以在创建对象时,对对象的属性等进行初始化
>如果一个类中定义了多个非静态代码块,则按照声明的先后顺序执行
>非静态代码块内可以调用静态的属性、静态的方法,或非静态的属性、非静态的方法
执行顺序:静态代码块——>构造器——>非静态代码块
4. 实例化子类对象时,涉及到父类、子类中静态代码块、非静态代码块、构造器的加载顺序:
由父及子,静态先行。
五、类的结构之五:内部类(实现某个类中单独需要的功能)
1.定义:Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类.
2.内部类的分类:
成员内部类(静态、非静态 ) vs 局部内部类(方法内、代码块内、构造器内)
3.成员内部类的理解:具有类和类方法的功能
一方面,作为外部类的成员:
* >调用外部类的结构
* >可以被static修饰
* >可以被4种不同的权限修饰(类只能两个:public,default)
*
另一方面,作为一个类:
* > 类内可以定义属性、方法、构造器等
* > 可以被final修饰,表示此类不能被继承。言外之意,不使用final,就可以被继承
* > 可以被abstract修饰
4.成员内部类:
4.1如何创建成员内部类的对象?(静态的,非静态的)
//创建静态的Dog内部类的实例(静态的成员内部类):直接类加载
Person.Dog dog = new Person.Dog();
//创建非静态的Bird内部类的实例(非静态的成员内部类):类的对象才可加载
//Person.Bird bird = new Person.Bird();//错误的
Person p = new Person();
Person.Bird bird = p.new Bird();
4.2如何在成员内部类中调用外部类的结构?
class Person{
String name = "小明";
public void eat(){
}
//非静态成员内部类
class Bird{
String name = "杜鹃";
public void display(String name){
System.out.println(name);//方法的形参
System.out.println(this.name);//内部类的属性
System.out.println(Person.this.name);//外部类的属性
//Person.this.eat();
}
}
}
5.局部内部类的使用:
//返回一个实现了Comparable接口的类的对象
public Comparable getComparable(){
//创建一个实现了Comparable接口的类:局部内部类
//方式一:
// class MyComparable implements Comparable{
//
// @Override
// public int compareTo(Object o) {
// return 0;
// }
//
// }
//
// return new MyComparable();
//方式二:
return new Comparable(){
@Override
public int compareTo(Object o) {
return 0;
}
};
}
注意点:局部内部类中方法间调用局部变量,该变量必须用final修饰。
在局部内部类的方法中(比如:show)如果调用局部内部类所声明的方法(比如:method)中的局部变量(比如:num)的话,要求此局部变量声明为final的。
*
jdk 7及之前版本:要求此局部变量显式的声明为final的
jdk 8及之后的版本:可以省略final的声明
总结:
成员内部类和局部内部类,在编译以后,都会生成字节码文件。
格式:成员内部类:外部类$内部类名.class
局部内部类:外部类$数字 内部类名.class