注意点
- 1.当一个对象被创建时,会对其中各种类型的成员变量自动进行初始化赋值。除了
基本数据类型之外的变量类型都是引用类型
- 2.方法的调用过程
Java的实参值如何传入方法?
java里方法的参数传递方式只有一种:值传递。 即将实际参数值的副本
(复制品)传入方法内,而参数本身不受影响。- 形参是基本数据类型:将实参基本数据类型变量的“数据值”传递给形参
- 形参是引用数据类型:将实参引用数据类型变量的“地址值”传递给形参
概念加深
重载
- 在同一个类中,允许存在一个以上的同名方法,只要他们的参数个数或者参数类型不同即可
- 特点:与返回值类型无关,只看参数列表,且参数列表必须不同(参数个数或参数类型,不同类型参数的顺序),调用时,只根据方法参数的不同来区别
- 示例:
可变参数
1 | //JDK 5.0以前:采用数组形参来定义方法,传入多个同一类型变量 |
说明:
- 声明格式:方法名(参数的类型名 …参数名)
- 可变参数:方法参数部分指定类型的参数个数是可变多个:0个,1个或多个
- 可变个数形参的方法与同名的方法之间,彼此构成重载
- 可变参数方法的使用与方法参数部分使用数组是一致的
- 方法的参数部分有可变形参,需要放在形参声明的最后
- 在一个方法的形参位置,最多只能声明一个可变个数形参
封装和隐藏
Java
中通过将数据声明为私有的(private)
,再提供公共的(public)
方法:getXxx()
和setXxx()
实现对该属性的操作,以实现下述目的:- 隐藏一个类中不需要对外提供的实现细节
- 使用者只能通过事先定制好的方法来访问数据,可以方便地加入控制逻辑,
限制对属性的不合理操作 - 便于修改,增强代码的可维护性
四种访问权限修饰符
- 对于
class
的权限修饰只可以用public
和default(缺省)
- public类可以在任意地方被访问
- default类只可以被同一个包内部的类访问
构造器
特征
- 它具有与类相同的名称
- 它不声明返回值类型。(与声明为void不同)
- 不能被static、final、synchronized、abstract、native修饰,不能有
return语句返回值
注意
- Java 语言中,每个类都至少有一个 构造器
- 默认构造器的修饰符与所属类的修饰符一致
- 一旦 显式定义了 构造器, 则系统 不再 提供默认 构造 器
- 一个类可以创建多个 重载 的构造器
- 父 类的构造器不可被子类继承
- 当父类中没有空参数的构造器时,子类的构造器必须通过
this(参 数列表)
或者super( 参数列表)
语句指定调用本类或者父类中相应的
构造器。同时,只能二选一
,且必须放在构造器的首行
说明
子类默认继承父类的属性和方法,但不会继承父类的构造器,而是在子类被实例化时会默认调用父类的空构造器(子类在创建的时候会调用自己的空构造器,并在空构造器会隐式调用super(),即父类的空构造器)。如果父类的构造器被重载,那么子类中的构造器也必须初始化父类的构造器,否则会报编译错误。当然,只要父类中显式定义了空构造器,子类中就不必初始化父类的构造器。
JavaBean
- 所谓
JavaBean
,是指符合如下标准的Java
类:- 类是公共的
- 有一个无参的公共的构造器
- 有属性,且有对应的get、set方法
UML类图
this 关键字
作用
- 它在方法内部使用,即这个方法所属对象的引用
- 它在构造器内部使用,表示该构造器正在初始化的对象
注意
- 1.在任意方法或构造器内,如果使用当前类的成员变量或成员方法可以在其前面添加this,增强程序的阅读性。不过,通常我们都习惯省略this
- 2.当形参与成员变量同名时,如果在方法内或构造器内需要使用成员变量,必须添加this来表明该变量是类的成员变量
3.使用this访问属性和方法时,如果在本类中未找到,会从父类中查找
4.this可以作为一个类中构造器相互调用(不能调用自身)的特殊格式,但不能通过
this(形参列表)
的方式调用自身构造器
1
2
3
4
5
6
7
8
9
10
11
12
13public Person(){ // 无参构造器
System.out.println("新对象实例化") ;
}
public Person(String name){
this(); // 调用本类中的无参构造器
this.name = name ;
}
public Person(String name,int age){
this(name) ; // 调用有一个参数的构造器
this.age = age;
}- 5.this(形参列表)”必须声明在类的构造器的首行
- 6.在类的一个构造器中,最多只能声明一个“this(形参列表)”
方法的重写
- 要求
- 1.子类重写的方法必须和父类被重写的方法具有相同的方法名称、参数列表
- 2.子类重写的方法的返回值类型要和父类被重写的方法的返回值类型相同或更小
- 3.子类重写的方法使用的访问权限不能小于父类被重写的方法的访问权限
- 4.子类不能重写父类中声明为private权限的方法
- 5.子类方法抛出的异常不能大于父类被重写方法的异常
- 6.子类与父类中同名同参数的方法必须同时声明为非static的(即为重写),或者同时声明为static的(不是重写)。因为static方法是属于类的,子类无法覆盖父类的方法
== 和 equals()
==
:- 基本类型比较值:只要两个变量的值相等,即为true。
- 引用类型比较引用(是否指向同一个对象):只有指向同一个对象时,==才
返回true - 用“==”进行比较时,符号两边的 数据类型必须兼容(可自动转换的基本
数据类型除外),否则编译出错
equals()
:- 所有类都继承了
Object
, 也就获得了equals()
方法 - 只能比较引用类型 , 其作用与 “==” 相同, 比较是否指向同一个对象,格式:
obj1.equals(obj2)
- 特例:当用
equals()
方法进行比较时 , 对类File 、String 、Date 及包装类 ( Wrapper Class )
来说 , 是比较类型及内容而不考虑引用的是否是同一个对像,原因:在这些类中重写了Object 类的equals() 方法
- 所有类都继承了
toString()方法
要点:
1.toString() 方法在Object 类中定义 , 其返回值是String 类型 , 返回类名和它
的引用地址在进行String 与其它类型数据的连接操作时 , 自动调用toString() 方法
1
2
3Date now=new Date();
System.out.println(“now=”+now); 相当于
System.out.println(“now=”+now.toString());可以根据需要在用户自定义类型中重写toString()
基本类型数据转换为String 类型时 ,的 调用了对应包装类的toString() 方法
1
2int a=10;
System.out.println(“a=”+a);几个典型实例
1
2
3
4
5
6
7
8char[] arr = new char[] { 'a', 'b', 'c' };
System.out.println(arr); // abc
System.out.println("arr = "+arr); // arr = [C@12a3a380
int[] arr1 = new int[] { 1, 2, 3 };
System.out.println(arr1); // [I@12a3a380
double[] arr2 = new double[] { 1.1, 2.2, 3.3 };
System.out.println(arr2); // [D@29453f44
包装类
拆箱: 获得 包装类对象中包装的基本类型变量
装箱:基本 数据类型包装成包装类的实例
在JDK1.5以前的版本中,表达式1和表达式2都要求是相同的类型,比如都是String或者char之类的,在JDK1.5以后,有了自动拆箱和装箱的原因,两者只要其中一种或者两者都能被拆箱即
例题
1
2
3
4
5
6
7
8
9
10
11
12Object o1 = true ? new Integer(1) : new Double(2.0);
System.out.println(o1); // 1.0
/**
三目运算符比较基本数据类型,所以在编译阶段自动拆箱为 int 和 double 类型,由于三目运算符要求 表达式2 和 表达式3 类型一致,所以在编译阶段自动类型提升(即 int 自动类型转换为 double 类型),再自动装箱为Object,输出时使用多态调用重写的toString();即Double包装类的toString();
*/
Object o2;
if (true)
o2 = new Integer(1);
else
o2 = new Double(2.0);
System.out.println(o2);// 1
static
- 使用:在Java类中,可用static修饰属性、方法、代码块、内部类
被修饰后的成员具备以下特点:
- 1.随着类的加载而加载
- 2.优先于对象存在
- 3.修饰的成员,被所有对象所共享
- 4.访问权限允许时,可不创建对象,直接被类调用
内存解析
注意点:
1.没有对象的实例时,可以用
类名. 方法名()
的形式访问由static修饰的类方法2.在static 方法内部只能访问类的
static 修饰的
属性或方法, 不能访问类的非非static 的结构
3.因为不需要实例就可以访问static 方法,因此static 方法内部不能有this(也不能有super)
4.static修饰的方法不能被重写
4的解释:
1
首先明确一点,在子类中重写父类的static方法,是不会报错的,编译也可以通过,但是在通过一个声明为父类,实际类型为子类的引用变量调用该方法时,发现被调用的仍是父类中原本以为会被覆盖的方法,不具有“多态”特性。
代码块
静态代码块:用static修饰的代码块
- 1.可以有输出语句
- 2.可以对类的属性、类的声明进行初始化操作
- 3.不可以对非静态的属性初始化。即:不可以调用非静态的属性和方法
- 4.若有多个静态的代码块,那么按照从上到下的顺序依次执行
- 5.静态代码块的执行要先于非静态代码块
- 6.静态代码块随着类的加载而加载,且只执行一次
非静态代码块:没有static修饰顶的代码块
- 1.可以有输出语句
- 2.可以对类的属性、类的声明进行初始化操作
- 3.除了调用非静态的结构外,还可以调用静态的变量或方法
- 4.若有多个非静态的代码块,那么按照从上到下的顺序依次执行
- 5.每次创建对象的时候,都会执行一次。且先于构造器执行
示例:
1
2
3
4
5
6
7class Person {
public static int total;
static {
total = 100;
System.out.println("in static block!");
}
}程序中成员变量赋值的执行顺序
- 1.声明成员变量的默认初始化
- 2.显式初始化、多个初始化块依次被执行(同级别下按先后顺序执行)
- 3.构造器再对成员进行初始化操作
- 4.通过”对象.属性”或”对象.方法”的方式,可多次给属性赋值
final
- 特点
- 1.final标记的类不能被继承
- 2.final标记的方法不能被子类重写
- 3.final标记的变量(成员变量或局部变量)即称为常量。名称大写,且只能被赋值1次
- 4.final标记的成员变量必须在声明时或在每个构造器中或代码块中显式赋值,然后才能使用
- 5.常量名要大写,内容不可修改
- 6.static final:全局常量
抽象类与抽象方法
- 注意点:
- 1.用
abstract关键字
来修饰一个类,这个类叫做抽象类 - 2.用
abstract
来修饰一个方法,该方法叫做抽象方法 - 3.抽象方法:只有方法的声明,没有方法的实现。以分号结束:比如:
public abstract void talk();
- 4.含有抽象方法的类必须被声明为抽象类
- 5.抽象类不能被实例化。抽象类是用来被继承的,抽象类的子类必须重写父类的抽象方法,并提供方法体。
- 6.不能用abstract修饰变量、代码块、构造器
- 7.不能用abstract修饰私有方法、静态方法、final的方法、final的类
- 1.用
接口
定义:
接口(interface)
是抽象方法和常量值定义的集合,(接口都是public abstract 修饰的,默认省略)特点:
- 1.用
interface
来定义 - 2.接口中的所有成员变量都默认是由
public static final
修饰的,(public static final
默认省略不写) - 3.接口中的所有抽象方法都默认是由
public abstract
修饰的 - 4.接口中没有构造器
- 5.接口采用多继承机制
- 1.用
示例
1
2
3
4
5
6public interface Runner {
public static final int ID = 1;
public abstract void start();
public abstract void run();
public abstract void stop();
}问题处理
- 若一个接口中定义了一个默认方法,而另外一个接口中也定义了一个同名同
参数的方法(不管此方法是否是默认方法),在实现类同时实现了这两个接
口时,会出现:接口冲突
- 若一个接口中定义了一个默认方法,而另外一个接口中也定义了一个同名同
- 解决:实现类必须覆盖接口中同名同参数的方法,来解决冲突
1
2
3
4
5
6
7
8class Man implements Filial, Spoony {
public void help() {
System.out.println("我该怎么办呢?");
Filial.super.help(); //这两句
Spoony.super.help(); //
}
}- 2.若一个接口中定义了一个默认方法,而父类中也定义了一个同名同参数的非
抽象方法,则不会出现冲突问题。因为此时遵守: 类优先原则。接口中具有
相同名称和参数的默认方法会被忽略。
内部类
- 定义:在Java中,允许一个类的定义位于另一个类的内部,前者称为内部类,后者
称为外部类 Inner class
一般用在定义它的类或语句块之内,在外部引用它时必须给出完
整的名称,Inner class
的名字不能与包含它的外部类类名相同;分类: 成员 内部类(static成员内部类和非static成员内部类)、局部内部类(不谈修饰符)、匿名内部类
成员内部类
- 作为类的成员的角色:和外部类不同,
Inner class
还可以声明为private或protected
; 可以调用外部类的结构,Inner class
可以声明为static
的,但此时就不能再使用外层类的非static的成员
变量 - 作为类的角色: 可以在内部定义属性、方法、构造器等结构,可以声明为
abstract
类 ,因此可以被其它的内部类继承,可以声明为final
的,编译以后生成OuterClass$InnerClass.class
字节码文件(也适用于局部内部类)
- 作为类的成员的角色:和外部类不同,
注意:
- 1.非static的成员内部类中的成员不能声明为static的,只有在外部类或static的成员
内部类中才可声明static成员 - 2.外部类访问成员内部类的成员,需要“内部类.成员”或“内部类对象.成员”的方式
- 3.成员内部类可以直接使用外部类的所有成员,包括私有的数据
- 4.当想要在外部类的静态成员部分使用内部类时,可以考虑内部类声明为静态的
- 1.非static的成员内部类中的成员不能声明为static的,只有在外部类或static的成员
局部内部类
如何声明局部内部类
1
2
3
4
5
6
7
8
9
10
11class 外部类{
方法(){
class 局部内部类{
}
}
{
class 局部内部类{
}
}
}如何使用?
- 只能在声明它的方法或代码块中使用,而且是先声明后使用。除此之外的任何地方都不能使用该类
- 但是它的对象可以通过外部方法的返回值返回使用,返回值类型只能是局部内部类的父类或父接口类型
- 局部内部类可以使用外部类的成员,包括私有的
- 局部内部类可以使用外部方法的局部变量,但是必须是final的
- 局部内部类和局部变量地位类似,不能使用public,protected,缺省,private
- 局部内部类不能使用static修饰,因此也不能包含静态成员
匿名内部类
定义:匿名内部类不能定义任何静态成员、方法和类,只能创建匿名内部类的一
个实例。一个匿名内部类一定是在new的后面,用其隐含实现一个接口或
实现一个类格式:
1
2
3new 父类构造器(实参列表)| 实现接口(){
// 匿名内部类的类体部分
}特点
- 匿名内部类必须继承父类或实现接口
- 匿名内部类只能有一个对象
- 匿名内部类对象只能使用多态形式引用