——- android培训、java培训、期待与您交流! ———-
3.0、静态代码块、构造代码块、构造函数
执行顺序:
(优先级从高到低。)静态代码块>mian方法>构造代码块>构造函数。
示例:
其中静态代码块只执行一次。构造代码块在每次创建对象是都会执行。
/*
1 普通代码块
普通代码块:在方法或语句中出现的{}就称为普通代码块。
普通代码块和一般的语句执行顺序由他们在代码中出现的次序决定
“先出现先执行”
*/
1
2 public class Code{
3 public static void main(String[] args){
4
5 {
6 int x=3;
7 System.out.println("1、普通代码块内的变量x="+x);
8 }
9
10 int x=1;
11 System.out.println("2、主方法内的变量x="+x);
12
13 {
14 int y=7;
15 System.out.println("3、普通代码块内的变量y="+y);
16 }
17 }
18}
19
20 /*
21 运行结果:
22 1、普通代码块内的变量x=3
23 2、主方法内的变量x=1
24 3、普通代码块内的变量y=7
25 */
26
2 静态代码块
/*
静态代码块:在java中使用static关键字声明的代码块。静态块用于初始化类,为类的属性初始化。
每个静态代码块只会执行一次。由于JVM在加载类时会执行静态代码块,所以静态代码块先于主方法执行。
如果类中包含多个静态代码块,那么将按照"先定义的代码先执行,后定义的代码后执行"。
注意:
1 静态代码块不能存在于任何方法体内。
2 静态代码块不能直接访问静态实例变量和实例方法,需要通过类的实例对象来访问。
*/
class Code{
{
System.out.println("Code的构造块");
}
static{
System.out.println("Code的静态代码块");
}
public Code(){
System.out.println("Code的构造函数");
}
}
public class Code3{
{
System.out.println("Code3的构造块");
}
static{
System.out.println("Code3的静态代码块");
}
public Code3(){
System.out.println("Code3的构造函数");
}
public static void main(String[] args){
System.out.println("Code3的主函数");
new Code();
new Code();
new Code3();
new Code3();
}
}
/*
Code3的静态代码块
Code3的主函数
Code的静态代码块
Code的构造块
Code的构造方法
Code的构造块
Code的构造函数
Code3的构造块
CodeB3的构造函数
Code3的构造块
Code3的构造函数
*/
3.1、构造函数
特点:
1、函数名与类名相同。
2、不用定义返回值类型。
3、没有具体的返回值。
作用:给对象进行初始化。
一般函数和构造函数的区别:
1)、 构造函数:对象创建时,就会调用与之对应的构造函数,对对象进行初始化。
2)、一般函数:对象创建后,需要函数功能时才调用。
构造函数:对象创建时,会调用并且只调用一次。
一般函数:对象创建后,可以被调用多次。
2、创建对象都必须要通过构造函数初始化。
一个类中如果没有定义过构造函数,那么该类中会有一个默认的空参数构造函数。
如果在类中定义了指定的构造函数,那么类中的默认构造函数就没有了。
3、多个构造函数是以重载的形式存在的。
注意事项:
1)、 在构造函数前面加上返回值就只是一般函数了。
2)、子类构造函数运行时,先运行了父类的构造函数。
原因:
1)、子类的所有构造函数中的第一行,其实都有一条隐身的语句super();
super(): 表示父类的构造函数,并会调用于参数相对应的父类中的构造函数。
而super():是在调用父类中空参数的构造函数。
2)、子类继承父类,会继承到父类中的数据,所以必须要看父类的数据初始化。
子类在进行对象初始化时,先调用父类的构造函数,这就是子类的实例化过程。
3)、子类中所有的构造函数都会默认访问父类中的空参数的构造函数,
因为每一个子类构造内第一行都有默认的语句super();
如果父类中没有空参数的构造函数,那么子类的构造函数内,
必须通过super语句指定要访问的父类中的构造函数。
如果子类构造函数中用this来指定调用子类自己的构造函数,
那么被调用的构造函数也一样会访问父类中的构造函数
3.2、构造代码块
/*
构造代码块:直接在类中定义且没有加static关键字的代码块称为{}构造代码块。
构造代码块在创建对象时被调用,每次创建对象都会被调用,
并且构造代码块的执行次序优先于类构造函数。
*/
public class Code2{
{
System.out.println("第一代码块");
}
public Code2(){
System.out.println("构造函数");
}
{
System.out.println("第二构造块");
}
public static void main(String[] args){
new Code2();
new Code2();
}
}
/*
执行结果:
第一代码块
第二构造块
构造函数
第一代码块
第二构造块
构造函数
*/
4.0 匿名、内部类
匿名内部类也就是没有名字的内部类
正因为没有名字, 所以匿名内部类只能使用一次, 它通常用来简化代码编写
但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口
例1:不使用匿名内部类来实现抽象方法
abstract class Person {
public abstract void eat();
}
class Child extends Person {
public void eat() {
System.out.println("eat something");
}
}
public class Two {
public static void main(String[] args) {
Person p = new Child();
p.eat();
}
}
/*
运行结果:eat something
可以看到,Child继承了Person类,然后实现了Child的一个实例,将其向上转型为Person类的引用
但是,Child类只使用一次,为了避免麻烦引入了匿名内部类
*/
例2:匿名内部类的基本实现
public class Demo {
public static void main(String[] args) {
Person p = new Person() {
public void eat() {
System.out.println("eat something");
}
};
p.eat();
}
}
/*运行结果:eat something
将抽象类Person中的方法在大括号中实现了省略一个类的书写
并且,匿名内部类还能用于接口上
例3:在接口上使用匿名内部类
interface Person2 {
public void eat();
}
public class Demo {
public static void main(String[] args) {
Person2 p = new Person2() {
public void eat() {
System.out.println("eat something");
}
};
p.eat();
}
}
/*
运行结果:eat something
*/
由上面的例子可以看出:
只要一个类是抽象的或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现
最常用的情况就是在多线程的实现上,因为要实现多线程必须继承Thread类或是继承Runnable接口
例4: Thread类的匿名内部类实现
public class Demo {
public static void main(String[] args) {
Thread t = new Thread() {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.print(i + " ");
}
}
};
t.start();
}
}
//运行结果:1 2 3 4 5
例5: Runnable接口的匿名内部类实现
public class Demo {
public static void main(String[] args) {
Runnable r = new Runnable() {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.print(i + " ");
}
}
};
Thread t = new Thread(r);
t.start();
}
}
//运行结果:1 2 3 4 5
4.1、java内部类总结
(1) 在方法间定义的非静态内部类:
● 外围类和内部类可互相访问自己的私有成员。
● 内部类中不能定义静态成员变量:
在外部类作用范围之外向要创建内部类对象必须先创建其外部类对象
(2) 在方法间定义的静态内部类:
● 只能访问外部类的静态成员:
静态内部类没有了指向外部的引用
(3) 在方法中定义的局部内部类:
● 该内部类没有任何的访问控制权限
● 外围类看不见方法中的局部内部类的,但是局部内部类可以访问外围类的任何成员。
● 方法体中可以访问局部内部类,但是访问语句必须在定义局部内部类之后。
● 局部内部类只能访问方法体中的常量,即用final修饰的成员。
(4) 在方法中定义的匿名内部类:
● 没有构造器,取而代之的是将构造器参数传递给超类构造器
当你只需要创建一个类的对象而且用不上它的名字时,使用匿名内部类可以使代码看上去简洁清楚。
5.0、抽象类: abstract
抽象:不具体,看不明白。抽象类表象体现。
在不断抽取过程中,将共性内容中的方法声明抽取,但是方法不一样,没有抽取,
这时抽取到的方法,并不具体,需要被指定关键字abstract所标示,声明为抽象方法。
抽象方法所在类一定要标示为抽象类,也就是说该类需要被abstract关键字所修饰。
5.1、抽象类的特点:
1:抽象方法只能定义在抽象类中,抽象类和抽象方法必须由abstract关键字修饰(可以描述类和方法,不可以描述变量)。
2:抽象方法只定义方法声明,并不定义方法实现。
3:抽象类不可以被创建对象(实例化)。
4:只有通过子类继承抽象类并覆盖了抽象类中的所有抽象方法后,才可以实例化,否则该子类还抽象类。
5.2、抽象类的细节:
1:抽象类中有构造函数,用于给子类对象进行初始化。
2:抽象类中是否可以定义非抽象方法?
可以。抽象类和一般类都是在描述事物,只不过抽象类在描述事物时,有些功能不具体。
所以抽象类和一般类都需要定义属性和行为。只不过,比一般类多了一个抽象函数。
而且比一般类少了一个创建对象的部分。
3:抽象关键字abstract和final , private , static不可以共存
4:抽象类中可以不定义抽象方法
6.0、关键字
6.1、主要概述:
Public: 访问权限最大。
static: 不需要对象,直接类名即可。
void: 主函数没有返回值。
Main: 主函数特定的名称。
(String[] args):主函数的参数,是一个字符串数组类型的参数,
jvm调用main方法时,传递的实际参数是 new String[0]。
jvm默认传递的是长度为0的字符串数组,我们在运行该类时,也可以指定具体的参数进行传递。
jvm会自动将这些字符串参数作为args数组中的元素,进行存储。
6.2、 this关键字
1、this代表其所在函数所属对象的引用。换言之,this代本类对象的引用。
当成员变量和局部变量重名,可以用关键字this来区分,this就是所在函数所属对象的引用。
简单说,哪个对象调用了this所在的函数,this就代表哪个对象。一般方法调用默认加this。
2、什么时候使用this关键字
当在函数内需要用到调用该函数的对象时,就用this。
6.3、static:
static关键字,是一个修饰符,用于修饰成员(成员变量和成员函数)。
特点:
1,想要实现对象中的共性数据的对象共享。可以将这个数据进行静态修饰。
2,被静态修饰的成员,可以直接被类名所调用。也就是说,静态的成员多了一种调用方式。类名.静态方式。
3,静态随着类的加载而加载。而且优先于对象存在。
弊端:
1,有些数据是对象特有的数据,是不可以被静态修饰的。因为那样的话,特有数据会变成对象的共享数据。
这样对事物的描述就出了问题。所以,在定义静态时,必须要明确,这个数据是否是被对象所共享的。
2,静态方法只能访问静态成员,不可以访问非静态成员。
因为静态方法加载时,优先于对象存在,所以没有办法访问对象中的成员。
3,静态方法中不能使用this,super关键字。
因为this代表对象,而静态在时,有可能没有对象,所以this无法使用。
4,主函数是静态的。
6.4、private
私有的访问权限最低,只有在本类中的访问有效。
注意:私有仅仅是封装的一种体现形式而已。依然可以被获取
私有权限:
其他类不能直接创建对象访问,所以只有通过本类对外提供具体的访问方式来完成对私有的访问
可以通过对外提供函数的形式对其进行访问,,set**(); get**();
好处:
可以在函数中加入逻辑判断等操作,对数据进行判断等操作
6.5、final:
特点:
1:这个关键字是一个修饰符,可以修饰类,方法,变量。
2:被final修饰的类是一个最终类,不可以被继承。
3:被final修饰的方法是一个最终方法,不可以被覆盖。
4:被final修饰的变量是一个常量,只能赋值一次。
其实这样的原因的就是给一些固定的数据起个阅读性较强的名称。
不加final修饰不是也可以使用吗?那么这个值是一个变量,是可以更改的。加了final,程序更为严谨。常量名称定义时,有规范,所有字母都大写,如果由多个单词组成,中间用 _ 连接。