代码块
代码块的分类:
1.局部代码块
2.构造代码块
3.静态代码块
4.同步代码块(多线程)
1.局部代码块 {局部代码块}
书写位置: 方法中
调用:
作用: 限制变量的作用域
2.构造代码块
书写位置: 类中方法外
调用: 1️⃣系统调用(在创建对象时,系统自动调用)
2️⃣在构造方法之前 构造代码块被系统调用
作用: 当你想 在每一个对象创建出来时 执行某些方法
可以在构造代码块之中调用
(作用是利用了特点,一创建对象就会执行构造代码块)
3.静态代码块(使用static修饰的代码块) static{ 静态代码块 }
书写位置:类中方法外
调用: 1️⃣随着类的加载而调用(与对象无关)
2️⃣只会加载一次(因为类只加载一次)
3️⃣加载类到方法区时,系统自动加载静态代码块
作用: 加载驱动程序(只加载一次)
// 举例
public class Demo01 {
static {
System.out.println("我是main的静态代码块");
}
public static void main(String[] args) {
{
int num = 0;
System.out.println("我就是局部代码块");
}
Person person = new Person();
}
}
class Person{
String name;
public Person() {
System.out.println("无参构造方法");
}
public Person(String name) {
this.name = name;
System.out.println("有参构造方法");
}
public void sayHi() {
System.out.println(name);
}
{
System.out.println("我是构造代码块");
}
// 静态代码块
static {
System.out.println("我是静态代码块");
}
}
// 执行结果:
我是main的静态代码块
我就是局部代码块
我是静态代码块
我是构造代码块
无参构造方法
面向对象特征之继承
面向对象的特征:封装,继承,多态
生活中的继承:
爷爷--->父亲--->儿子(继承链)
DNA DNA DNA
姓氏 姓氏 姓氏
公司 公司
豪车
(依次传递给后代)
* 继承的特点*
1.继承链
2.继承有传递性
3.继承: 继承属性 和 行为
4.建立类与类之间的关系(继承关系)
1.使用继承的条件
必须要符合生活逻辑,才能使用继承
(技巧:子类是父类 如:狗 是 动物)
若是不符合生活逻辑,怎么使用继承?
将相同的 属性,行为提取出来,组成新的类,当做父类
写法:
关键字 extends
子类 extends 父类
public class Demo03 {
public static void main(String[] args) {
Cat c1 = new Cat();
c1.name = "加菲";
c1.age = 2;
c1.sayHi();
}
}
/*
* 动物类
* 姓名 年龄
* 猫类
* 姓名 年龄 喵喵喵
* 狗类
* 姓名 年龄 汪汪汪
*/
class Animal{
String name;
int age;
public void sayHi() {
System.out.println(name + ": " + age);
}
}
class Cat extends Animal{
public void speak() {
System.out.println("喵喵");
}
}
class Dog extends Animal{
public void speak() {
System.out.println("汪汪");
}
}
2.继承的好处
1️⃣减少代码量
2️⃣提高工作效率
3️⃣增强了代码的复用性
3.继承的坏处
1️⃣高内聚:指一个类的 内部方法的联系程度
(例:方法fun2依靠方法fun1,fun3依靠fun2; 只要修改fun1,fun2和fun3改变)
2️⃣低耦合:类与类之间的 尽量减少联系(修改一个类,其他的类可能会改变)
// 设计模式基本上都是为了解耦(降低耦合度)
Java中的继承(类与类之间的继承关系)
单继承
// 多继承(仅体现在接口)
1.java 允许 多层继承(继承链)
A---->B---->C
比如要使用继承链中 特有的方法 使用哪个类
一般使用继承链中 末端的类
比如要使用继承链中 共有的方法 使用哪个类
public class Demo {
public static void main(String[] args) {
// java中所有的类 如果没有写继承哪个类
// 默认 继承 Object类
// Object类 是所有类的基类
// 直接打印对象 实际上是调用了
// Object类中的 toString()方法
DemoA a = new DemoA();
System.out.println(a);
}
}
class DemoA{
String name;
public void sayHi() {
System.out.println(name);
}
}
class DemoB extends DemoA{
}
class DemoC extends DemoB{
String gender;
}
**java: 继承中的构造方法(通过super调用父类的构造方法)**
注意:构造方法是不能继承的(继承的特点: 继承 属性和行为;而且构造方法名与父类相同)
// 举例:构造方法在继承中的应用
public class Demo {
public static void main(String[] args) {
// 创建儿子对象
// 无参构造方法
// 为什么会调用父类的无参构造方法?
// 保证继承完整性
// 创建子类对象时 为了保证继承的完整性
// 会默认通过super() 调用父类的无参构造方法
Son f1 = new Son();
Son f2 = new Son("哈哈");
}
}
class Father{
String name;
// 无参
public Father(){
super(); // 表示Father类的父类 是Object类的对象
System.out.println("我是Father类的 无参构造方法");
}
// 有参
public Father(String name){
System.out.println("我是Father类的 有参构造方法");
}
// 介绍自己的方法
public void sayHi() {
System.out.println(name);
}
}
class Son extends Father{
// 无参
public Son() {
// 系统会在子类的构造方法的 第一行(先继承,再执行自己)
super(); // 调用父类的无参构造方法(默认隐藏)
System.out.println("我是Son类的 无参构造方法");
}
// 有参
public Son(String name) {
// super();
System.out.println("我是Son类的 有参构造方法");
}
}
- super和this 的作用
this 在类中表示 本类的对象
继承中 this.属性
系统会先从本类中寻找该属性(行为),找到就输出
没找到就去寻找父类 都没找到就报错super 在子类中表示 父类的对象
super 也可以调用父类中的方法
super(); // 调用父类的构造方法
super.方法名(); // 调用父类的成员方法
思考:如果父类中没有提供无参的构造方法,咋整?(系统未提供)
说明:该类中 一定有一个有参的构造方法
注意:为了规范,写代码 必须提供一个无参构造方法(无参有参都写)
* javaBean规范(按书写顺序):
* 1.成员变量私有化
* 2.必须提供无参的构造方法
* 3.提供set/get方法
// 解决办法
/* 可以在构造方法的第一行
调用有参的构造方法super("参数") 来保证继承的完整性
只要在子类的构造方法中 调用父类的构造方法就行
不管有参还是无参
*/
class Car{
String name;
// public Car() {
// System.out.println("我是Car类的 无参构造方法");
// }
public Car(String name) {
System.out.println("我是Car类的 有参构造方法");
}
}
class Audi extends Car{
public Audi() {
// 调用父类的 有参构造方法
super("哈哈");
System.out.println("我是Audi类的 无参构造方法");
}
public Audi(String name) {
super("哈哈");
System.out.println("我是Audi类的 有参构造方法");
}
}
方法的重载和重写
1.方法的重载:
方法的重载(Overload)
前提:方法都在一个类中
当方法的功能相同,但是内部实现不同,可以使用重载
2.方法的重写
方法的重写(Override)
前提:类与类之间必须建立继承关系
作用:相当于对原方法 功能上的一个提升
写法:方法和父类的完全一致 才是方法重写
// 例子1:
class Test1{
public void fun() {
System.out.println("我是Test1的 fun方法");
}
}
class Test2 extends Test1{
// 重写fun方法
public void fun() {
// 可以在重写的方法中 调用父类的原方法
// 可以让功能进行升级
super.fun();
System.out.println("我是Test2的 fun方法");
}
}
// 例子2:
class IOS7{
String name = "苹果";
String color = "red";
public void siri() {
System.out.println("我会说English");
}
}
class IOS8 extends IOS7{
// 注解 标识下面的方法 是重写父类的方法
@Override
public void siri() {
super.siri();
System.out.println("我会说Chinese");
}
// 重写Object类中 toString()方法
// 可以代替之前的 介绍自己的方法 来输出对象的所有属性
@Override
public String toString() {
// TODO Auto-generated method stub
System.out.println("hah");
return "姓名 = " + name + " " + "颜色 = " + color;
}
}
//创建 子类对象
public class Demo {
public static void main(String[] args) {
IOS8 i = new IOS8();
i.siri();
// 意愿: 直接输出对象的时候
// 希望可以把该对象的所有成员变量打印出来
System.out.println(i.toString());
}
}
final关键字
1.用途:
1️⃣修饰变量 变量不能更改值(相当于把变量 变成了常量)
2️⃣修饰方法 方法不能被重写
3️⃣修饰类 该类不能被继承
public class Demo09 {
public static void main(String[] args) {
// 1️⃣ final 基本数据类型
// 不能修改值
final int a = 10;
// a = 15;
System.out.println(a);
// 1️⃣ final 引用数据类型
// 不能修改地址(对象的属性 随便改)
final Test3 t1 = new Test3();
t1.name = "haha";
// t1 = new Test3();
}
}
// 2️⃣
final class Test3{
String name;
// 静态常量
// 命名规范: 所有单词使用大写 多个单词用下划线连接(易区分)
// 无效值
public static final int MAX_VALUE ;
// 可以使用构造方法 或者构造代码块 对常量赋值(只能一次)
// public Test3() {
// MAX_VALUE = 10;
// }
{
MAX_VALUE = 10;
}
// 3️⃣
final public void fun() {
}
}
/*class Test4 extends Test3{
// public void fun() {
//
// }
}*/