首页 >> 大全

java学习笔记2--面向对象编程

2023-10-18 大全 37 作者:考证青年

目录 2.类和对象 2.6 练习--内存分配2.7 匿名对象 3.方法 3.2 方法重载 3.3 可变个数的形参 3.4 方法的值传递机制 4.递归(后面补)5.封装 6.构造器 7.==属性赋值的过程==8..UML类图10.this关键字 11.和关键字 12.项目2--客户信息管理系统 12.2 增删改查操作 12.3 12.4 内存解析 13.继承 13.5 实例化对象时构造器的执行顺序 14. 方法的重写 14.3 调用14.4 重写与重载的区别14.5 意义 15.super关键字(表示父类的xxx) 15.3 为什么super(…)或this(…)调用语句只能作为构造函数中的第一句出现?15.4 this和super的区别 16.子类对象实例化的过程17.多态(向上转型) 17.3 作用17.4 向下转型 17.5 练习17.6 多态是编译时行为还是运行时行为?17.7 ==练习--多态调用的是子类中重写的方法==17.8 动态绑定机制(==继承也适用==) 18.类 18.4 "=="和()的区别18.5 ()练习18.6 ()方法 19.单元测试 20.包装类 20.7 ==int和进行比较== 21.关键字 21.6 单例模式 22.理解 main 方法的语法 23.代码块 23.2 非静态代码块 23.3 ==程序中加载顺序== 23.4 ==属性赋值的执行顺序== 24.final关键字 25. 关键字 25.3 抽象方法 25.4 细节25.5 抽象类与普通类的区别25.6 不能修饰静态方法、私有方法、final方法、final类25.7 抽象类匿名子类的匿名对象 25.8 模板方法设计模式 25.8 抽象方法应用实例 26.接口 26.2 接口中的成员 26.3 ==抽象类与接口的异同==26.4 应用实例26.5 父类的变量和接口中的变量相同 27.内部类 27.2 成员内部类 27.3 局部内部类

1.面向对象与面向过程

完整笔记

1.1 面向过程 以过程为中心的编程思想,分析出解决问题所需要的步骤,用函数将这些步骤实现,使用时依次调用即可。强调的是功能行为,以函数为最小单位,考虑怎么做。 1.2 面向对象 面向对象编程( ,OOP,面向对象程序设计)的主要思想是把构成问题的各个事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙一个事物在整个解决问题的步骤中的行为。强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。 2.类和对象 2.1 定义

类:对一类事物的描述,是抽象的、概念上的定义;(人类)

对象:类的一个实例;(具体某个人)

举例:我们跟控制台交互需要使用java提供的类,使用时我们要创建一个对象,通过这个对象来操作它的功能方法,完成我们和控制台的交互。

2.2 类的成员 Filed = 属性 = 成员变量 = 行为 = 成员方法构造器代码块内部类 2.3 类和对象的使用 创建类,设计属性和行为;创建类的对象(实例化对象);通过对象调用类的属性和方法; 2.4 内存结构

对于引用数据类型来说,变量值不是null就是地址值(包含变量类型);

2.5 成员变量和局部变量对比

成员变量定义在类中方法外,除了成员变量其余变量都是局部变量;

2.5.1 相同点 定义格式相同:数据类型 变量名 = 变量值;都是先定义后使用;都有其对应的定义域; 2.5.2 不同点 在内存中加载的位置不同:成员变量在堆中(非);局部变量在栈中。权限修饰符的不同:成员变量可以添加权限修饰符( 缺省 );局部变量不可以。在类中声明的位置不同:成员变量直接声明在类中,方法体外;局部变量声明在方法、形参、构造器形参、构造器内部。默认初始值不同:成员变量有默认初始值,与一维数组相同;局部变量除形参外,都需要显示初始化。 2.5.3 定义域

成员变量的定义域是整个类中,局部变量定义域是在其最近一层的结构中(方法、代码块);

成员变量可以定义在类的任意位置,对于非静态的成员变量,它是随着对象的创建而产生的,而非静态的结构都是通过对象来调用,所以成员变量的定义位置与其被调用的结构的位置无关;

局部变量初始化必须在被调用的结构之前,因为无论是方法中还是代码块中,都是自上向下执行的,必须执行完局部变量的初始化语句,才会给局部变量分配内存空间;

两者的定义位置归根到底还是与其生命周期有关;

2.6 练习–内存分配

画出如下代码在执行时的内存分配情况
class Car{String color = "red";int num = 4;void show(){int a = 10;System.out.println("color="+color+",num="+num);}}
class CarTest {public static void main(String[] args) {Car c1 = new Car();   Car c2 = new Car(); c1.color = "blue";  c1.show();   c2.show();}  }

2.7 匿名对象 理解:我们创建的对象,没有显示的赋值给一个变量名。即为匿名对象。特征:匿名对象只能调用一次。使用:充当方法的实参。 3.方法 3.1 定义

权限修饰符 返回值类型 方法名(形参列表){方法体;
}

3.1.1 权限修饰符 3.1.2 返回值类型 3.1.3 方法名

标识符,和变量的命名规范一样,首单词的首字母小写,其余单词首字母大写。

3.1.4 参数列表

格式:数据类型1 形参1,数据类型2 形参2,…

3.1.5 3.1.6 注意 3.2 方法重载 3.2.1 意义

重载的最直接作用是方便了开发人员可以根据不同的参数个数,顺序,类型,自动匹配方法,减少了方法的命名和记忆。

3.2.2 定义

在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。

“两同一不同”:同一个类,同一个方法名;形参列表不同。

3.2.3 特点(两同一不同,四无关) 3.3 可变个数的形参

5.0 中提供了( of )机制,允许直接定义能和多个实参相匹配的形参。从而,可以用一种更简单的方式,来传递个数可变的实参。

3.3.1 格式

数据类型 … 形参名称

定义:public void max(String... str) {// 与数组的遍历方式相同for (int i = 0; i < str.length; i++) {System.out.println(str[i]);}}
调用:(两种方式)对象.max("a","b","c");对象.max(new String[]{"a","b"});

3.3.2 细节 3.3.3 与数组的区别 3.4 方法的值传递机制 3.4.1 变量的赋值复习 3.4.2 形参和实参 3.4.3 形参的传递机制:值传递 3.4.4 练习1

public class TransferTest3{public static void main(String args[]){TransferTest3 test=new TransferTest3();test.first();}public void first(){int i=5;Value v=new Value();v.i=25;second(v,i);System.out.println(v.i+" "+i);}public void second(Value v,int i){i=0;v.i=20;Value val=new Value();v=val;System.out.println(v.i+" "+i);}
}
class Value {int i= 15;
} 

15 0
20 5

3.4.5 练习2

方法1:在method方法中输出a、b,并终止程序;private static void method(int a, int b) {System.out.println("a = " + 100);System.out.println("b = " + 200);System.exit(0); // 终止程序}

方法2:重新println方法private static void method(int a, int b) {PrintStream ps = new PrintStream(System.out){public void println(String x){if("a=10".equals(x)){x = "a=100";}else if("b=10".equals(x)){x = "b=200";}super.println(x);}};System.setOut(ps);}

3.4.6 练习3

微软: 定义一个int型的数组:int[] arr = new int[]{12,3,3,34,56,77,432};

让数组的每个位置上的值去除以首位置的元素,得到的结果,作为该位置上的新值。遍历新的数组。

//错误写法:如果从arr[0]开始,那么arr[0]就变为1了,其余值都是除以1。
for(int i= 0;i < arr.length;i++){arr[i] = arr[i] / arr[0];
}//正确写法1
for(int i = arr.length –1;i >= 0;i--){arr[i] = arr[i] / arr[0];
}//正确写法2
int temp = arr[0];
for(int i= 0;i < arr.length;i++){arr[i] = arr[i] / temp;
}

3.4.7 练习4

(char[] arr)方法体是对char[]数组进行遍历

 * int[] arr = new int[10];* System.out.println(arr);//地址值* * char[] arr1 = {'a','b','c'};* System.out.println(arr1);//abc

4.递归(后面补) 5.封装 5.1 定义

封装指的是将类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过类中提供的公共方法来实现对隐藏信息的操作和访问。

5.2 目的

追求程序设计的“高内聚,低耦合”特性,提高系统的可拓展性和可维护性。

当我们创建一个类的对象以后,我们可以通过"对象.属性"的方式,对对象的属性进行赋值。这里,赋值操作要受到属性的数据类型和存储范围的制约。但除此之外,没有其他制约条件。但是,实际问题中,我们往往需要给属性赋值加入额外限制条件。这个条件就不能在属性声明时体现,我们只能通过方法进行条件的添加。比如说,。同时,我们需要避免用户再使用“对象.属性”的方式对属性进行赋值。则需要将属性声明为私有的()此时,针对于属性就体现了封装性。

5.3 封装性的体现 5.4 权限修饰符

Java 权限修饰符、、(缺省)、置于类的成员定义前,用来限定对象对该类成员的访问权限。

5.5 权限修饰符之于封装

封装性的实现需要权限修饰符的配合–Java 提供了 4种权限修饰符来修饰类及类的内部结构,体现类及类的内部结构在被调用时的可见性大小。

6.构造器 6.1 格式

    权限修饰符 类名(形参列表) {方法体;}

6.2 作用 6.3 细节 7.属性赋值的过程 默认初始化显式初始化构造器初始化通过“对象.属性”或“对象. 方法”给属性赋值

正确顺序:1 -> 2 -> 3 -> 4 8.

有一个无参的公共的构造器

/** JavaBean 是一种 Java 语言写成的可重用组件。* 所谓 javaBean,是指符合如下标准的 Java 类:* 		> 类是公共的* 		> 有一个无参的公共的构造器* 		> 有属性,且有对应的 get、set 方法* */
public class Customer {private int id;private String name;public Customer(){}public void setId(int i){id = i;}public int getId(){return id;}public void setName(String n){name = n;}public String getName(){return name;}
}

9.UML类图

介绍类以及类内部结构

10.this关键字 10.1 作用

this表示当前对象或者当前正在创建的对象(相对于构造器来说),可以用来修饰、调用属性,方法,构造器。

10.2 使用方法

this.属性(用来区分形参与成员变量)
this.方法()
this(形参列表) //在构造器中调用本类中其余构造器

1 在类的方法中,我们可以使用"this.属性"或"this.方法"的方式,调用当前对象属性和方法。

通常情况下,我们都选择省略“this.”。特殊情况下,如果方法的形参和类的属性同名,我们必须显式地使用"this.变量"的方式,表明此变量是属性,而非形参。

2 在类的构造器中,我们可以使用"this.属性"或"this.方法"的方式,调用正在创建的对象属性和方法。

但是,通常情况下,我们都选择省略“this.”。特殊情况下,如果构造器的形参和类的属性同名,我们必须显式地使用"this.变量"的方式,表明此变量是属性,而非形参。

3.this 调用构造器(减少代码冗余)

① 我们可以在类的构造器中,显式的使用"this(形参列表)“的方式,调用本类中重载的其他的构造器!

② 构造器中不能通过"this(形参列表)“的方式调用自己。

③ 如果一个类中声明了n个构造器,则最多有n -1个构造器中使用了"this(形参列表)”。

④ "this(形参列表)"必须声明在类的构造器的首行!

⑤ 在类的一个构造器中,最多只能声明一个"this(形参列表)”。

4.this也可以单独使用,表示当前对象;super不可以单独使用。

10.3 和

idea快捷键alt+;

方法中不用加this,因为没有重名的形参;

    private String name;public void setName(String name){this.name = name;}public String getName(){return name;}

11.和关键字 11.1 包 11.2 导入 12.项目2–客户信息管理系统 12.1 12.1.1 sc.next()和sc.()

        Scanner sc = new Scanner(System.in);System.out.print("输入:");String s = sc.next();  //不会读入空格System.out.print("输出:");System.out.println(s);

输入:  123 123  2312
输出:123

        Scanner sc = new Scanner(System.in);System.out.print("输入:");String s = sc.nextLine();  //不会读入空格System.out.print("输出:");System.out.println(s);

输入:   12321 2312 213  
输出:   12321 2312 213  

12.1.2 try-catch- 12.2 增删改查操作 12.2.1 删除一个用户

数组中删除一个元素后,后边元素都要前移。

    public boolean delCustomer(int index) {if (index >= total || index < 0)return false;for (int i = index; i < total - 1; i++) {customers[i] = customers[i + 1];}customers[total - 1] = null;total--;return true;}

12.3 12.3.1 12.4 内存解析

13.继承

完整笔记

13.1 定义

当多个类中拥有相同的属性和方法时,将这些内容抽取到一个单独的类中,别的类就不需要定义这些类或方法,直接继承哪一个类即可。

格式:class A B{}

13.2 目的 13.3 细节 13.4 向上查找原则(每一个父类都是一个子类) 13.4.1 规则

因为方法可以重写,而属性不能重写,所以方法满足动态绑定机制,而属性是就近原则。

多态是在继承的基础上实现的,多态主要的作用是提高代码的通用性,所以继承和多态的方法和属性调用逻辑相同。

方法:编译看左边,运行看右边。(普通继承等号左右是同一个类)

属性:编译看左边,运行看左边。

13.4.2 例题(重要) 上面的规则,注意在类A中的this是new B(), super代表A。try-catch-中,在try中执行之前始终会执行里面的代码,如果里面有,则数据跟随改变并返回,不会再执行try中的。如果没有,则原数据不跟随里改变的数据改变!

class Test {public static void main(String[] args) {System.out.println(new B().getValue()); // }static class A {protected int value;public A (int v) {setValue(v);}public void setValue(int value) {this.value= value;}public int getValue() {try {value ++;return value;} finally {this.setValue(value);System.out.println(value);}}}static class B extends A {public B () {super(5);setValue(getValue()- 3);}public void setValue(int value) {super.setValue(2 * value);}}
}

22 34 17

13.5 实例化对象时构造器的执行顺序

先执行父类的构造器,在执行子类构造器中的语句。

14. 方法的重写 14.1 定义

方法的重写是指子类继承父类后,可以对父类同名同参数的方法进行覆盖操作;

14.2 细节(两小一大)

子类:重写方法;

父类:被重写方法;

如果子类的方法与父类的方法同名同参数,那么子类一定要满足重写的规则,不然编译报错

14.2.1 权限修饰符(大) 14.2.2 返回值类型(小) 14.2.3 异常(小) 14.2.4 14.3 调用 14.4 重写与重载的区别

14.5 意义

父类方法中的逻辑不适用于子类,所以子类需要对父类的方法进行重写。

15.super关键字(表示父类的xxx) 15.1 作用

在子类中使用,可以调用父类的属性、方法或者构造器;

15.2 使用

super.属性/方法/构造器

15.2.1 属性和方法 15.2.2 构造器 15.3 为什么super(…)或this(…)调用语句只能作为构造函数中的第一句出现?

无论通过哪个构造器创建对象,都要保证先初始化父类;

目的:当子类继承父类后,继承了父类中所有的属性和方法,因此子类有必要知道父类是如何进行初始化的。

15.4 this和super的区别

super不可以单独使用

16.子类对象实例化的过程 17.多态(向上转型) 17.1 对多态的理解

一种事物具有多种状态。

17.2 使用 17.2.1 使用前提 17.2.2 格式

父类引用指向子类对象(向上转型):父类名称 父类引用 = new 子类名称();

// 1,2两种写法相同,都是向上转型
子类 子类对象 = new 子类();
父类 父类引用 = 子类对象;// 1
父类 父类引用 = (父类名称)子类对象; //2 

17.2.3 多态的使用:虚拟方法调用

虚拟方法:子类重写了父类的方法,在多态情况下,将此时父类的方法称为虚拟方法,父类根据赋给它的不同子类对象,动态调用属于子类的该方法。这样的方法调用在编译期是无法确定的,只能在运行期间确定。(多态情况下,父类中被重写的方法称为虚拟方法)

编译看左边,运行看右边:有了对象多态性以后,我们在编译期,只能调用父类声明的方法,但在执行期实际执行的是子类重写父类的方法。

Java引用变量有两个类型:编译时类型和运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。==若编译时类型和运行时类型不一致,就出现了对象的多态性()。==多态情况下,

“看左边”:看的是父类的引用(父类中不具备子类特有的方法)

“看右边”:看的是子类的对象(实际运行的是子类重写父类的方法)

17.2.4 注意事项 17.3 作用

提高了代码的通用性,常称作接口重用

17.4 向下转型

17.4.1 作用

多态情况下,内存中实际上加载了子类中特有的成员方法和属性,但是由于变量声明为父类类型,导致编译时只能调用父类的成员,无法直接调用子类中特有的成员,所以要通过向下转型将父类引用转为子类对象。(类似于强制转换)

17.4.2 格式

子类名称 对象名 = (子类名称)父类引用

17.4.3 关键字

格式:x A:检验x的运行类型是否为类A或A子类的对象,返回值为型。

作用:避免向下转型时,出现java.lang.异常。

17.4.4 向下转型的常见问题

		//问题一:编译时通过,运行时不通过//举例一
//		Person p3 = new Woman();
//		Man m3 = (Man)p3;//举例二Person p4 = new Person();Man m4 = (Man)p4;//问题二:编译通过,运行时也通过Object obj = new Woman();Person p = (Person)obj;//问题三:编译不通过
//		Man m5 = new woman();//		String str = new Date();//		Object o = new Date();
//		String str1 = (String)o;

17.5 练习

/** 练习:子类继承父类* * 1.若子类重写了父类方法,就意味着子类里定义的方法彻底覆盖了父类里的同名方法,* 系统将不可能把父类里的方法转移到子类中。* * 2.对于实例变量则不存在这样的现象,即使子类里定义了与父类完全相同的实例变量,* 这个实例变量依然不可能覆盖父类中定义的实例变量* */
public class FieldMethodTest {public static void main(String[] args){Sub s= new Sub();System.out.println(s.count);	//20s.display();//20Base b = s;//==:对于引用数据类型来讲,比较的是两个引用数据类型变量的地址值是否一样。System.out.println(b == s);	//trueSystem.out.println(b.count);	//10 编译看左边,运行也看左边b.display(); // 20 多态:编译看左边,运行看右边}
}class Base {int count= 10;public void display() {System.out.println(this.count);}
}class Sub extends Base {int count= 20;public void display() {System.out.println(this.count);}
}

17.6 多态是编译时行为还是运行时行为?

多态时运行时行为。

 * 证明见如下:
import java.util.Random;class Animal  {protected void eat() {System.out.println("animal eat food");}
}class Cat  extends Animal  {protected void eat() {System.out.println("cat eat fish");}
}class Dog  extends Animal  {public void eat() {System.out.println("Dog eat bone");}
}class Sheep  extends Animal  {public void eat() {System.out.println("Sheep eat grass");}}public class InterviewTest {public static Animal  getInstance(int key) {switch (key) {case 0:return new Cat ();case 1:return new Dog ();default:return new Sheep ();}}public static void main(String[] args) {int key = new Random().nextInt(3);System.out.println(key);// 通过使用随机数,可以知道多态时运行时的行为;Animal  animal = getInstance(key);animal.eat();}
}

17.7 练习–多态调用的是子类中重写的方法

public class InterviewTest1 {public static void main(String[] args) {Base base = new Sub();base.add(1, 2, 3); //sub_1Sub s = (Sub)base;s.add(1,2,3); // sub_2}
}class Base {public void add(int a, int... arr) {System.out.println("base");}
}class Sub extends Base {public void add(int a, int[] arr) {System.out.println("sub_1");}public void add(int a, int b, int c) {System.out.println("sub_2");}}

17.8 动态绑定机制(继承也适用) 17.8.1 为什么只有非静态的成员方法有动态绑定机制

因为多态是在重写的基础上实现的,只有非静态方法可以重写,而静态方法和属性都不可以重写,所以只有非静态的成员方法有动态绑定机制。

17.8.2 定义

17.8.3 使用

对于多态或继承来说,调用成员方法时,执行的是运行时类型的方法(就是子类中重写的方法),如果子类中没有进行重写,就会去调用父类中的方法;如果在调用的方法中还有方法调用,那么还是先执行运行时类型的方法,没有再向上找;

public class DynamicBinding {public static void main(String[] args) {A a = new B();//向上转型System.out.println(a.sum());// 30System.out.println(a.sum1());// 20}
}class A {public int i = 10;public int sum() {return getI() + 10;}public int sum1() {return i + 10;}public int getI() {return i;}
}class B extends A {public int i = 20;//    public int sum() {
//        return i + 20;
//    }//    public int sum1() {
//        return i + 10;
//    }public int getI() {return i;}
}

18.类 18.1 类的基本介绍 18.2 "=="运算符 18.3 ()方法 18.3.1 类中源码

    public boolean equals(Object obj) {return (this == obj);}

18.3.2 细节 18.3.3 重写()方法

idea中可以使用alt+自动生成;

重写()方法时,如果属性也是自定义类,那么属性所属类中的()方法也要重写;

    public boolean equals(Object o) {
//        1.比较两个对象的内存地址if (this == o) return true;
//        2.判断o是否为空,不为空再比较两者的类型是否一致if (o == null || getClass() != o.getClass()) return false;
//        3.向下转型Test1 test1 = (Test1) o;
//        4.比较两者的属性是否相等
//        对于引用数据类型的属性,要先判断对象是否为空,不为空才能调用equals方法return age == test1.age && Objects.equals(name, test1.name);}public static boolean equals(Object a, Object b) {return (a == b) || (a != null && a.equals(b));}

18.4 "=="和()的区别 18.5 ()练习

int it = 65;
float fl = 65.0f;
System.out.println(“65和65.0f是否相等?” + (it == fl)); //true
char ch1 = 'A'; char ch2 = 12;
System.out.println("65和'A'是否相等?" + (it == ch1));//true
System.out.println(“12和ch2是否相等?" + (12 == ch2));//true
String str1 = new String("hello");
String str2 = new String("hello");
System.out.println("str1和str2是否相等?"+ (str1 == str2));//false
System.out.println("str1是否equals str2?"+(str1.equals(str2)));//true
System.out.println(“hello” == new java.util.Date()); //编译不通过

18.6 ()方法 18.6.1 类中的定义方法

public String toString() {return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

18.6.2 细节

1..out.(对象); 和.out.(对象.());当对象不是null时,两者效果相同;当对象为null时,直接会输出null,调用方法会报空指针异常;

2.像、Date、File、包装类等都重写了类中的()方法,使得在调用()时,返回"实体内容"信息;

3.char[]数组也重写了同方法;

4.自定义类如果重写()方法,当调用此方法时,返回对象的"实体内容".

5.与其它类型数据进行连接操作时,自动调用()方法,对于基本数据类型则是调用包装类的()方法;

18.6.3 举例

public class ToStringTest {public static void main(String[] args) {Customer cust1 = new Customer("Tom" ,21);System.out.println(cust1.toString());	//github4.Customer@15db9742System.out.println(cust1); 	//github4.Customer@15db9742 ---> Customer[name = Tom,age = 21]String str = new String("MM");System.out.println(str);Date date = new Date(45362348664663L);System.out.println(date.toString());	//Wed Jun 24 12:24:24 CST 3407}
}

    public void test() {char[] arr = new char[] { 'a', 'b', 'c' };System.out.println(arr);//abcint[] arr1 = new int[] { 1, 2, 3 };System.out.println(arr1);//[I@722c41f4double[] arr2 = new double[] { 1.1, 2.2, 3.3 };System.out.println(arr2);//[D@5b80350b}

19.单元测试 19.1 要求 19.2 idea中添加模板

在live-中添加了代码模板,快捷键是test;

19.3 使用

import org.junit.Test;/*** @Description:* @author:zhou* @create: 2022-01-22 16:56*/
public class JUnitTest {@Testpublic void testEquals(){System.out.println("123");}@Testpublic void test123(){System.out.println("456");
//        System.out.println(1/0);}}

20.包装类

包装类是引用数据类型,变量的默认值是null

20.1 8种基本数据类型对应的包装类 基本数据类型包装类

int

byte

Byte

short

Short

long

Long

float

Float

char

20.2 基本数据类型转为包装类

使基本数据类型拥有类的特性(方法,属性),常用自动装箱

        int i = 123;
//        方法1:将基本数据类型当作参数传入Integer构造器Integer n = new Integer(i);System.out.println(n); // 通过println输出时,n和n.toString()的效果相同System.out.println(n.toString());//        方法2:通过字符串参数构造包装类对象,字符串中的类型一定要与包装类兼容Integer n1 = new Integer("123");System.out.println(n);Float f = new Float(23.1);System.out.println(f);Double d = new Double("23.1");System.out.println(d);//        方法3:自动装箱Integer n2 = 5;System.out.println(n2.toString());

20.3 包装类转为基本数据类型

包装类转为基本数据类型,可以进行运算;常用自动拆箱

//        方式1:通过包装类的xxxValue()方法Integer i = new Integer(123);int i1 = i.intValue();System.out.println(i1);
//        方式2:自动拆箱int i2 = i;System.out.println(i2);

20.4 基本数据类型、包装类转为

//        方式1:直接与""连接Integer i = new Integer(123);String s = i + "";System.out.println(s);//        方式2:调用String的valueOf()方法int i1 = 234;String s1 = String.valueOf(i1);System.out.println(s1);

20.5 转为基本数据类型

使用包装类的()方法,返回值类型是基本数据类型;

使用包装类的()方法;

没有()方法,使用的()方法就行;

        int i2 = Integer.parseInt(s1);System.out.println(i2+1);

20.6 面试题 20.6.1 习题1

类中内置了一个数组,里面存放的是[-128,127]的所有整数,如果使用自动装箱的方式赋值并且数值在[-128,127],那么就可以直接使用数组中的元素,不用new新的对象,提高了效率;如果超过这个范围,就需要new新对象;

public void method1() {
Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.println(i == j); // false
Integer m = 1;
Integer n = 1;
System.out.println(m == n);// true
Integer x = 128;
Integer y = 128;
System.out.println(x == y);// false
}

20.6.2 习题2

通过方法可以得知,缓存在第一次使用时初始化,所以说如果已经创建了一个缓存中的整数,使用创建第二次时,不会使用new关键字,而用已经缓存的对象。所以使用方法创建两次对象,若对应的数值相同,且数值在-128~127之间时,两个对象都指向同一个地址。 i = 400这样的方式来创建对象,与方法的效果是一样的。

_java学习笔记2--面向对象编程_java学习笔记2--面向对象编程

    public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);
}

20.7 int和进行比较

int1 == ,是int的封装类,当与int进行==比较时,就会拆箱成一个int类型,所以还是相当于两个int类型进行比较,这里的,不管是直接赋值,还是new创建的对象,只要跟int比较就会拆箱为int类型,所以就是相等的。

21.关键字

完整笔记

21.1 意义

我们有时候希望无论是否产生对象,无论产生了多少个对象,某些特定的内容在内存中只有一份,这样可以节省内存空间。

21.2 使用

可以用来修饰属性、方法、代码块、内部类,表示这些内容都是属于类的,所有对象共享一份,任何对象去访问修改都是同一个。

21.2.1 修饰属性 21.2.2 修饰方法 21.3 细节 21.4 内存解析

21.5 什么时候需要静态变量和静态方法 21.5.1 静态变量

如果需要让一个类中的所有对象都共享一个变量,那么就可以考虑静态变量。例如:定义了一个类,需要统计所有学生个数,可以使用静态变量来做计数器。

21.5.2 静态方法 21.6 单例模式 21.6.1 设计模式定义

设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。可以理解为套路。就像是经典的棋谱,不同的棋局,我们用不同的棋谱。不同的英雄拥有不同的连招。

21.6.2 单例模式

定义:所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。

三大要素:私有构造器,存放当前类对象的静态变量(因为静态方法不能访问非静态成员),提供给外界获取对象的静态方法。

21.6.3 饿汉型

优点:线程安全;

缺点:随着类的加载而创建对象,所以对象的生命周期过长;

**注意事项:**如果不提供静态方法,而是直接将属性改为的,在外部也可以通过调用属性获取对象,但是违背了封装性的原则,因为此时在外部可以随意修改属性的值。如果仍然想使用属性获取对象,那么可以将属性变为 final,这样外部就不能修改属性值了。

public class SingleTon {private SingleTon() {}private static SingleTon singleTon = new SingleTon();public static SingleTon getSingleTon() {return singleTon;}
}

public class SingleTon {private SingleTon() {}public static final SingleTon singleTon = new SingleTon();
}

21.6.4 懒汉型

优点:第一次调用静态方法时创建对象,延迟对象创建,减少系统开销;

当前写法线程不安全
class SingleTon2{private SingleTon2(){}private static SingleTon2 singleTon2;public static SingleTon2 getSingleTon2(){if(singleTon2==null){singleTon2 = new SingleTon2();}return singleTon2;}
}

21.6.5 单例模式的优点

由于单例模式只生成一个实例,减少了系统性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决。

21.6.6 单例模式的应用 22.理解 main 方法的语法 22.1 main()方法格式解析

由于 Java 虚拟机需要调用类的 main()方法,所以该方法的访问权限必须是 ,又因为 Java 虚拟机在执行 main()方法时不必创建对象,所以该方法必须是 的,该方法接收一个 类型的数组参数,该数组中保存执行 Java 命令时传递给所运行的类的参数。

22.2 细节 23.代码块 23.1 静态代码块 23.1.1 格式

{代码块内容;}

23.1.2 细节 23.2 非静态代码块 23.2.1 格式

{代码块内容;}

23.2.2 细节 23.3 程序中加载顺序

总原则:由父及子,静态先行。

23.3.1 练习1

过程:

1.想要创建对象,先要加载类的信息,因为“由父及子”,所以先加载父类的信息(类 -> Root类 -> Mid类 -> Leaf类),静态代码块随类的加载而执行,所以就先执行三个类中的静态代码块和静态成员变量(按照在程序中出现的顺序初始化);

2.类的信息加载完毕,然后创建对象,非静态代码块和普通成员变量随对象的创建而执行,且先于构造器的执行,所以先执行父类中的非静态代码块、普通成员变量(按照在程序中出现的顺序初始化),接着执行父类中的构造器,然后执行子类的;

3.第二次创建对象时,静态代码块不再执行。

class Root{static{System.out.println("Root的静态初始化块");}{System.out.println("Root的普通初始化块");}public Root(){System.out.println("Root的无参数的构造器");}
}
class Mid extends Root{static{System.out.println("Mid的静态初始化块");}{System.out.println("Mid的普通初始化块");}public Mid(){System.out.println("Mid的无参数的构造器");}public Mid(String msg){//通过this调用同一类中重载的构造器this();System.out.println("Mid的带参数构造器,其参数值:"+ msg);}
}
class Leaf extends Mid{static{System.out.println("Leaf的静态初始化块");}{System.out.println("Leaf的普通初始化块");}	public Leaf(){//通过super调用父类中有一个字符串参数的构造器super("123");System.out.println("Leaf的构造器");}
}
public class LeafTest{public static void main(String[] args){new Leaf(); new Leaf();}
}

Root的静态初始化块
Mid的静态初始化块
Leaf的静态初始化块
Root的普通初始化块
Root的无参数的构造器
Mid的普通初始化块
Mid的无参数的构造器
Mid的带参数构造器,其参数值:尚硅谷
Leaf的普通初始化块
Leaf的构造器
--------------------------------------------------------
Root的普通初始化块
Root的无参数的构造器
Mid的普通初始化块
Mid的无参数的构造器
Mid的带参数构造器,其参数值:尚硅谷
Leaf的普通初始化块
Leaf的构造器

23.3.2 练习2

静态代码块优于main()方法的执行

class Father {static {System.out.println("11111111111");}{System.out.println("22222222222");}public Father() {System.out.println("33333333333");}
}public class Son extends Father {static {System.out.println("44444444444");}{System.out.println("55555555555");}public Son() {System.out.println("66666666666");}public static void main(String[] args) { // 由父及子 静态先行System.out.println("77777777777");System.out.println("************************");new Son();System.out.println("************************");new Son();System.out.println("************************");new Father();}
}

11111111111
44444444444
77777777777
************************
22222222222
33333333333
55555555555
66666666666
************************
22222222222
33333333333
55555555555
66666666666
************************
22222222222
33333333333

23.4 属性赋值的执行顺序

1.默认初始化

2.显式初始化或者非静态代码块初始化(看两者声明的先后顺序)

3.构造器初始化

4.调用对象.属性或对象.方法进行赋值

24.final关键字 24.1 练习1

    public class Something {public int addOne(final int x) {return ++x;  编译错误,x不能重新赋值// return x + 1; 正确,没有赋值操作} }

24.2 练习2

public class Something {
public static void main(String[] args) {
Other o = new Other();
new Something().addOne(o);
}
public void addOne(final Other o) {
// o = new Other();  错误,不能重新赋值
o.i++;  正确,引用数据类型变量中的内容可以改变,因为其属性不是final} }
class Other {
public int i; }

25. 关键字 25.1 意义

如果一个方法不确定方法体的内容,可以将该方法声明为抽象的,到子类中去重写该方法,该方法所在的类是抽象类。

25.2 抽象类 25.2.1 格式

权限修饰符 abstract  class 类名{}

25.3 抽象方法 25.3.1 格式

权限修饰符 abstract 返回值类型 方法名(形参列表)

25.4 细节 25.5 抽象类与普通类的区别

抽象类只比普通类多了定义抽象方法的功能,而且不能被实例化,其它没有什么不同(都可以有任意的成员)。

25.6 不能修饰静态方法、私有方法、final方法、final类 25.7 抽象类匿名子类的匿名对象 25.7.1 抽象类匿名子类的对象

class EmployeeTest {public static void main(String[] args) {Employee是抽象类,匿名子类是不创建抽象类的子类直接使用下面的形式来创建对象,需要重写所有的抽象方法Employee e = new Employee() {@Overridepublic void work() {System.out.println();}};}
}
public abstract class Employee {public Employee() {}public abstract void work();}

25.7.2 抽象类匿名子类的匿名对象

class EmployeeTest {public static void main(String[] args) {需要重写所有的抽象方法new Employee() {@Overridepublic void work() {System.out.println();}}.work();}
}
public abstract class Employee {public Employee() {}public abstract void work();}

25.8 模板方法设计模式 25.8.1 模板方法的应用 25.8.2 例子

public class TemplateTest {public static void main(String[] args) {SubTemplate subTemplate = new SubTemplate();subTemplate.sendTime();}}abstract class Template {public final void sendTime() {long start = System.currentTimeMillis();code();long end = System.currentTimeMillis();System.out.println(end = start);}
//  将code抽象化,让子类重写protected abstract void code();
}class SubTemplate extends Template {@Overrideprotected void code() {for (int i = 0; i < 1000; i++) {for (int j = 0; j < 1000; j++) {}}}
}

25.8 抽象方法应用实例 26.接口

完整笔记

26.1 概述 26.1.1 定义

接口就是规范,定义的是一组规则,体现了现实世界中“如果你是/要…则必须能…”的思想。==继承是一个"是不是"(is a)的关系,而接口实现则是"能不能"的关系。==接口的本质是契约,标准,规范,就像我们的法律一样。制定好后大家都要遵守。

26.1.2 格式

权限修饰符  interface 接口名1,接口名2,....{}

26.1.3 意义 26.1.4 细节 26.1.5 实现类

格式:权限修饰符 class 类名 父类名 接口名{}

26.1.6 接口和类之间的关系

26.2 接口中的成员 26.2.1 JDK1.8之前

接口中只能有全局常量和抽象方法;

26.2.2 JDK1.8之后

接口中增加了静态方法(1.8)、默认方法(1.8)、私有方法(1.9)、私有静态方法(1.9);

26.2.3 默认方法

格式:[] 返回值类型 方法名(参数){}

26.2.4 静态方法

格式:[] 返回值类型 方法名(参数){}

26.2.5 抽象方法

格式:[] [] 返回值类型 方法名();

26.2.6 私有方法和私有静态方法

格式: [] 返回值类型 方法名(参数){}

26.2.7 全局常量

格式:[ final] 类型 变量名 = 变量值;

26.3 抽象类与接口的异同 26.4 应用实例 26.5 父类的变量和接口中的变量相同

interface  A{int x = 0;
}
class B{int x =1;
}
class C extends B implements A {public void pX(){System.out.println(x);  //super.x   A.x}public static void main(String[] args) {new C().pX();}
}
答案:错误。在编译时会发生错误(错误描述不同的JVM有不同的信息,意思就是未明确的x调用,
两个x都匹配(就象在同时import java.util和java.sql两个包时直接声明Date一样)。对于父类的变量,可以用super.x来明确,
而接口的属性默认隐含为 public static final.所以可以通过A.x来明确。

27.内部类 27.1 概述 27.1.1 定义

允许一个类A声明在另一个类B的内部,那么类A就是内部类,类B是外部类;根据类声明的位置,分为成员内部类(静态和非静态)和局部内部类(方法内、代码块内、构造器内);

27.1.2 不同类的权限修饰符 27.1.3 意义

只有当前类使用此结构,所以定义为内部类。

27.2 成员内部类 27.2.1 作为外部类的成员 27.2.2 作为一个类 27.2.3 实例化内部类

静态成员内部类:.A a = new .A();

非静态成员内部类: = new (); .B b = .new B();

public class InnerClass {public static class A{
//        成员内部类}class B{}}

27.2.4 细节 27.2.5 内部类中调用外部类成员 27.2.6 例题

public class OuterClass { private double d1 = 1.0; //insert code here 
} 
You need to insert an inner class declaration at line 3. Which two inner class declarations are 
valid?(Choose two.) 
A. class InnerOne{public static double methoda() {return d1;}} 
B. public class InnerOne{static double methoda() {return d1;}} 
C. private class InnerOne{double methoda() {return d1;}} 
D. static class InnerOne{protected double methoda() {return d1;}} 
E. abstract class InnerOne{public abstract double methoda();} 
说明如下:
一.静态内部类可以有静态成员,而非静态内部类则不能有静态成员。 故 AB 错
二.静态内部类的非静态成员可以访问外部类的静态变量,而不可访问外部类的非静态变量;return d1 出错。 
故 D 错
三.非静态内部类的非静态成员可以访问外部类的非静态变量。 故 C 正确
四.答案为CE 

27.3 局部内部类

完整笔记

使用较少,一般使用匿名内部类

局部内部类只能在方法内部使用,出了方法就不能使用

27.3.1 匿名内部类 匿名内部类必须继承父类或实现接口。匿名内部类对象只能使用多态形式引用,父类引用指向子类对象。重写接口中所有的抽象方法是因为只有非抽象的类才能创建对象,除了抽象方法,匿名内部类中可以重写父类或接口中的任意方法来实现自己的需求。

接口名称 变量名 = new 父类构造器(实参列表)|实现接口(){重写接口中所有的抽象方法}

27.3.2 练习

public class Test {public static void main(String[] args) {   // 创建了一个Object类的子类对象重写了Object中的equals方法,并赋值给父类引用,// 所以使用对象o调用的是子类重写的方法Object o = new Object() {  public boolean equals(Object obj) {  return true; }};   System.out.println(o.equals("Fred"));}
}

27.3.3 匿名内部类的匿名对象

new 接口名称(){重写接口中所有的抽象方法}.方法();

27.3.4 注意事项

局部内部类中访问所在方法的局部变量时,这个局部变量必须是final的(java8之后可以省略)。因为从生命周期角度来说,new一个内部类对象是在堆中,而局部变量在栈中,方法结束后出栈,局部变量消失,而内部类的对象还存在堆中,等待垃圾回收; 后边在说

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了