Java学习的第三周

Java学习的第三周

壹:

1.代码块

在Java中,使用{}括起来的代码被称为代码块,根据其位置和声明的不同,可以分为局部代码块, 构造代码块,静态代码块,同步代码块(多线程讲解)。 

局部代码块  在方法中出现;限定变量生命周期,及早释放,提高内存利用率 

构造代码块  在类中方法外出现;多个构造方法方法中相同的代码存放到一起,每次调用构造都执行,并且在构造方法前执行 

静态代码块 在类中方法外出现,加了static修饰 在类中方法外出现,并加上static修饰;用于给类进行初始化,在加载的时候就执行,并且值执行 一次

2.继承

定义:
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属 性和行为,只要继承那个类即可。 通过extends关键字可以实现类与类的继承 

单独的这个类称为父类,基类或者超类;这多个类可以称为子类或者派生类。 有了继承以后,我们定义一个类的时候,可以在一个已经存在的类的基础上,还可以定义自己的新成员。
格式:
class 子类名 extends 父类名 {} 
优点:
继承的好处:

提高了代码的复用性 多个类相同的成员可以放到同一个类中 

提高了代码的维护性 如果功能的代码需要修改,修改一处即可 

让类与类之间产生了关系,是多态的前提 其实这也是继承的一个弊端:类的耦合性很强
设计原则:
1:设计原则:

高内聚低耦合。

简单的理解: 内聚就是自己完成某件事情的能力。 
耦合就是类与类之间的关系。
继承特点:
Java只支持单继承,不支持多继承。 一个类只能有一个父类,不可以有多个父类。 
class SubDemo extends Demo{} //ok 
class SubDemo extends Demo1,Demo2...//error Java支持多层继承(继承体系) 
class A{} 
class B extends A{} 
class C extends B{} 
注意事项:
子类只能继承父类所有非私有的成员(成员方法和成员变量) 
其实这也体现了继承的另一个弊端:打破了封装性 
子类不能继承父类的构造方法,但是可以通过super(后面讲)关键字去访问父类构造方法。 不要为了部分功能而去继承 
我们到底在什么时候使用继承呢? 
继承中类之间体现的是:”is a”的关系。
    
	1:在父类中定义私有方法,然后来一个子类,然后在测试类创建子类对象调用发现使用不了。 其实通过父类也使用不了,不过,在父类中是可以使用的。
        
    2:我们发现两个类有部分代码相同,我们就让这两个类产生一个继承关系,这是不对的,代码演示。 
        
    3:我们要想知道什么时候使用继承,就必须知道继承间类的关系: 举例:水果和苹果,苹果是一种水果。 学生和人,学生是人的一种。

继承中成员变量的关系:
案例演示    
子父类中同名和不同名的成员变量 结论:    
在子类方法中访问一个变量    
首先在子类局部范围找    
然后在子类成员范围找    
最后在父类成员范围找(肯定不能访问到父类局部范围)    
如果还是没有就报错。(不考虑父亲的父亲…)
访问成员变量:
 * 			this.变量名  :访问本类的成员变量
 * 			super.变量名: 访问父类的成员变量
 * 		访问成员方法:
 * 			this.方法名() ;访问本类的成员方法
 * 			super.方法名();访问父类的成员方法
 * 		访问构造方法:
 * 			this():表示访问的是本类的无参构造方法
 * 			this(xx);表示访问本类的有参构造方法
 * 
 * 			super() ;表示访问父类的无参构造方法
 * 			super(xx); 表示访问父类的有参构造方法

3.super关键字

super的用法和this很像 

this代表本类对应的引用

super代表父类存储空间的标识(可以理解为父类引用) 用法(thissuper均可如下使用)     

访问成员变量        
this.成员变量  super.成员变量   

访问构造方法(子父类的构造方法问题讲)         
this()  super() 访问成员方法(子父类的成员方法问题讲) this.成员方法() super.成员方法()

4.继承中构造方法的关系

子类中所有的构造方法默认都会访问父类中空参数的构造方法 为什么呢? 
    
因为子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类 数据的初始化。 
    
每一个构造方法的第一条语句默认都是:super()
如何父类中没有构造方法,该怎么办呢?  
子类通过super去显示调用父类其他的带参的构造方法  
子类通过this去调用本类的其他构造方法  
本类其他构造也必须首先访问了父类构造 
一定要注意: super()或者this(.)必须出现在第一条语句山 否则,就会有父类数据的多次初始化
问题:如果父类的无参构造方法没有提供,那么子类构造会出现什么情况?
 * 	子类的所有构造方法默认父类的无参构造方法,父类如果没有提供,就报错了!
 * 
 * 	如何解决呢?
 * 		1)手动给出父类的无参构造方法 (之前说在写一个标准类的时候,建议永远给出无参构造方法)
 *		2)现在手动不提供无参构造方法,如何解决?	
 *			2.1)间接的通过super(xx)来访问父类的有参构造初始化!
 *			2.2)通过this(),访问本类(子类)的无参构造方法,然后在通过子类的无参构造方法里面super(xx)
 *					间接访问父类的有参;
 * 
 * 根据上面的总结:
 * 	子类中的所有构造方法里面某一个构造方法必须让父类初始化,super(xx),this(),
练习:
编译----> ExtendsTest3.class Person.class Student.class 

/*
 *静态代码块的特点:随着类的加载而加载,优先于对象存在 (只执行一次)
 *优先级:静态代码块 > 构造代码块  > 构造方法
 *
 *在内存中:检查当前整个Java文件的代码结构:继承关系(跟父类相关的静态的东西优先于执行,然后子类的静态相关的在执行!)
 *
 *子类继承父类,子类的所有构造方法默认父类的无参构造方法(分层初始化),先让父类初始化,再是子类初始化

```java
 * 
 * */
 class Person{
	static {
		System.out.println("Person的静态代码块");
	}
	{
		System.out.println("Person的构造代码块");
	}
	public Person() {
		System.out.println("Person的构造方法");
	}
}
class Student extends Person{
	static {
		System.out.println("Student的静态代码块");
	}
	{
		System.out.println("Student的构造代码块");
	}
	public Student() {
		//super();
		System.out.println("Student的构造方法");
	}
}
public class ExtendsTest3 {//
	public static void main(String[] args) {
		Student s = new Student() ;
		System.out.println("---------------");
		Student s2 = new Student() ;	
	}
}

**结果为:**

Person的静态代码块
Student的静态代码块
Person的构造代码块
Person的构造方法
Student的构造代码块
Student的构造方法


## 贰:

### 1.final关键字

**1.修饰类       该类不能被继承**

**2.修饰变量     该变量不能被重新赋值**

**3.修饰方法     该方法不能被重写**

```java
for(int i = 0; i < 10; i++){
	final int c = i;                //  因为每一次赋值都是一个全新的变量c
	System.out.println(c);
}

2.继承中的方法调用

1.方法不同名

​ 通过子类对象分别调用即可

2.方法同名

​ 如果在子类中存在该方法就调用子类的方法

​ 如果子类中不存在该方法就去父类中找,如果存在就调用父类的方法

​ 如果都不存在,则不存在这个方法

3.代码块

​ 分类: 静态代码块, 构造代码块, 局部代码块

​ 执行顺序: 静态代码块 > 构造代码块 > 局部代码块

3.多态

1.多态的前提条件:

​ 1).必须有继承关系

​ 2).方法重写,子类继承父类,将父类的功能覆盖

2.多态访问的特点:

成员变量: 编译看左,运行看左

成员方法: 编译看左,运行看右

静态方法: 编译看左,运行看左

3.构造方法:

​ 存在继承关系(分层初始化) 先让父类初始化,再让子类初始化

4.多态的弊端:

​ 不能访问子类特有的方法

​ 怎么解决这个问题 : 1.向下转型 (强制类型转换)

叁:

1.抽象类(重点)

1)抽象类的特点: 如果一个类中有抽象方法,那这个类一定是抽象类

​ 如果一个类是抽象类,那么该类不一定含有抽象方法.

2)抽象类不能进行实例化:

​ 需要通过子类进行实例化, 即抽象类多态

3)抽象方法的格式:

​ 权限修饰符 abstract 返回值类型 方法名(形式参数)

抽象类 必须强制子类完成的事情(将抽象类中所有的抽象方法重写)

2.抽象类的特点

3.接口(重点)

1.接口的匿名内部类

返回的是接口的子实现类的对象

4.抽象类和接口的比较(Java8中)

相同点:	
		1) 都是抽象类型;
		2) 都可以有实现方法 (以前接口不行)
		3) 都可以不需要实现类或者继承者去实现所有方法 (以前不行, 现在接口中默认方法不需要实现者实现)
不同点:
        1) 抽线类不可以多重继承,接口可以 (无论是多重继承还是多重行为继承)
        2) 抽象类和接口所反映出的设计理念不同. 其实抽象类表示的是"is a"关系	
        3) 接口中定义的变量默认是public static final,且必须给出其初值,所以实现类中不能重新定义,也不能改变其值;
            friendly型,其值可以在子类中重新定义,也可以重新赋值.

注意:

如果一个类, 类属变量及方法不以public , protect, private 这三种修饰符来修饰, 它就是friendly类型的, 那么包类的
           任何类都可以访问它, 而包外的任何类都可以访问它, 而包外的任何类都可以访问它 (包括包外继承了此类的子类), 因
           此, 这种类, 类属变量及方法对包内的其他类是友好的, 开放的, 而对包外的其他类是关闭的.

5.内部类

分类:

​ 成员内部类

​ 局部内部类

1.成员内部类

​ 特点: 在一个类成员位置创建一个新类 : 成为成员内部类

​ 成员内部类中可以访问外部类的成员变量, 成员方法等 包括私有的

​ 外部类访问内部类的成员需要创建内部类的对象来访问:

​ **格式:**外部类名.内部类名.对象名 = new 外部类名().内部类名().

内部部类访问外部类的变量必须声明为final

(注意,若使用JDK1.8,方法中内部类的方法是可以直接访问外部类的方法的局部变量,并且不需要声明为final类型。)

2.局部内部类

​ 特点: 在一个成员方法中构建一个新类

​ 局部内部类不可以使用public或者private访问修饰符进行声明,因为它作用域仅仅被限定在声明这个局部类的块中

​ 与其他的内部类相比,局部类还有一个其他内部类所不具备的有优点。它不仅可以访问包含它们的外部类,还可以访问局部变量,但是这些局部变量必须声明为final,它们一旦被赋值,就不能被改变。

4.匿名内部类(重点)

格式: new 类名(){

方法重写;

}:

本质是: 一个类的子类或者是一个接口的子实现类的对象.

1.匿名内部类作为参数传递:(重点)**

class Test {
	public static void main(String[] args) {
	
	PersonDemo pd = new PersonDemo ();
  //pd.method(new Student());// 正常写法,可以传递传递匿名
	pd.method(new Person() {//匿名内部类在开发中当做参数传递
			public void show() {
				System.out.println("show");
			}
		});
	}
}
//抽象类或者接口
abstract class Person {
	public abstract void show();
}
 
class PersonDemo {
	
	//public void method(Person p) {  //  以前的写法,先创建										 //  多态,再使用		 
	/*
	Person p = new Person(){
		public void show() {
			System.out.println("show");
		}
	};
	*/
public void method(Person p) {//Person p=new Student();		//父类引用指向子类对象
		p.show();
	}
}
 
class Student extends Person {
	public void show() {
		System.out.println("students show");
	}
}

肆:

1: 编译时期常量:

​ (JVM)不需要加载,常量也存在内存中

​ 例如:static final int y = 10;

2: 运行时期常量:

​ 需要JVM加载

例如:static final Integer i = new Integer(100)

伍:

问题描述:

Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
String s = sc.nextLine(); // 出错 会将回车识别为字符串而录入字                           //  符串失败 

解决办法:

创建两个键盘录入对象:

Scanner sc1 = new Scanner(System.in);
Scanner sc2 = new Scanner(System.in);
int a  = sc1.nextInt();     
String = sc2.nextLine();    // 使用另一个键盘录入对象录入字符串

陆:

1.Object类中的toString:

​ 自定义类需要重写该方法, 否则打印对象时, 输出的是地址值.

​ 常用类基本上都重写了该方法, 不用自己重写 , 直接使用即可

2.Object类中的equals方法:

== :

​ 对于两个变量来说, 比较的是值的内容是否相同

​ 对于引用类型变量表示的是比较它们地址值是否相同

**注意:**1. 变量值类型是存储在内存中的栈中,而引用类型的变量在栈中仅仅是存储引用类型变量的地址,其本身的对象实例数据则存储在堆中。

2.只有被final修饰的基本数据类型和String类型变量存放在常量池中。

​ 自定义类重写equals方法, 比较时比较的是对象的成员信息

​ 常用类也重写了该方法,例如:String

简单说就是,== 比较的是栈内容,equals比较的是堆内容

总结:

1.使用 == 比较

Java中的8种基本数据类型(byte,short,char,int,long,float,double,boolean)比较他们之间的值是否相等

引用数据类型,比较的是他们在堆内存地址是否相等。每新new一个引用类型的对象,会重新分配堆内存空间,使用==比较返回false

2.equals 的作用:

引用类型默认情况下,比较内存地址值是否相等。可以按照需求逻辑,重写对象的equals方法。

3.包装类对象的比较

**包装类对象使用 == 和 equals进行比较的结果:**
package equalsdemo;

public class EqualsTest {
	public static void main(String[] args) {
		Integer a = new Integer(20);
		Integer b = new Integer(20);
		System.out.println(a==b);  //   false
		System.out.println(a.equals(b));  //  true
	}
}

总结: 包装类对象也属于引用类型

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值