面向对象
1.类和对象
类:指的是一类事物。
对象:是类的实体。就像数据库中的一条记录。转换到java中,就用一个对象来表示
2.类的组成
类由方法 属性 内部类 代码块组成
3.声明类的语法格式
修饰符 class 类名{
属性名
方法名
}
4.对象的创建
通过new 关键字来调用其构造方法创建对象例如
Person P = new Person();
下面是对象的内存分析图
5.对象的成员之一------属性
5.1.语法格式
修饰符 属性类型 属性名称;
5.2.变量的分类
-
按照数据类型可以分为基本数据类型 vs 引用数据类型
-
按照变量的作用域来分可以分为成员变量vs 局部变量
成员变量和局部变量的区别
1.声明格式都一样共同点
不同点
- 位置不同 成员变量在方法的外面,类的里面,局部变量在方法的里面。
-权限修饰符不同 局部没有权限修饰符。
默认值不同。成员默认值为 0 空 那些。局部没有默认值
在内存中的位置不同。成员在堆中,局部在栈中
6.类的成员二☞-----方法
6.1命名
要做到见名指意
6.2方法的类型
-
public void show(){}无参无返回
-
public int getAge(){};无参有返回
-
public void say (String str){}:有参无返回
-
public String getName(String name){};有参有返回
6.3方法的格式
权限修饰符 返回值类型 名称(形参列表){
方法体(调用的时候才会执行)
}
6.4 return
-
用来返回方法的返回值
-
用来退出方法
7.方法的重载(overload)
在一个类中允许一个以上的同名方法。 但是这些方法,必须参数类型不同。或者参数个数不同。这就是方法的重载特点: 是否重载 看的是 方法名是否相同。方法的参数个数是否相同。参数的类型是否相同。
8.方法的参数传递☆
当方法的参数是基本数据类型是。传的是本身的值 当方法的参数是引用类型时,传递的是实参的地址。
9.面向对象三大特性之一-----封装性
1.封装性的步骤
1.将属性私有化
2.提供公共的get和set方法
2.封装性的作用
假如没有封装性的话。那么我们在直接赋值。在项目中有些值只能赋值为那些范围。如果
我们让别直接赋值。但是别人赋的值不在那个方法。可能会引起麻烦。
10.权限修饰符
11.构造方法
11.1.构造器格式
修饰符 类名(参数列表){
方法体
}
11.2注意
-
java中每一个类都有一个构造器。如果没有写构造器。那么默认会调用无参的构造器。
-
默认构造器的权限修饰符。和类的修饰符一样
-
如果定义了显示构造器,那么默认的无参构造器就没了
-
一个类可以重载多个构造器。
-
构造器不可被继承
12. javaBean
-
javaBean的类是公共的。
-
有一个无参的构造器
-
有属性,且有对应的get和set方法
13 .UML图
14. this关键字
-
this代表当前对象的引用
-
this可以用来调用属性 方法 构造器
-
在方法中。如果局部变量和成员变量同名。那么调用this.变量名。是通过当前对象的引用来掉他对应的成员变量的名字。直接写名字。那就是调用局部变量。
-
在构造器中。
-
使用this(参数)可以调用其他构造器。但是这个代码必须写在第一句。
-
如果有n个构造器。那么他们之间不能存在环。如果存在环那么就错误了。
-
15.package和import
package
-
作用 : java为了将类进行统一的管理和划分,提供了包的概念。
-
说明 :
-
1.包名遵守标识符的规则和规范。xxxyyyzzz2.每“.”一次代表一层目录 3.不同的包下面的类的类名可以相同 4.组织机构的类型(com.edu + 组织机构的名称 + 项目名 + 模块名 例 : com.atguigu.chat.login 5.包名可以告诉编译器字节码所需要存放的目录。 6.package只能在源文件的首
-
import
1.在源文件中使用import显式的导入指定包下的类或接口 2.声明在包的声明和类的声明之间。(声明的位置) 3.如果需要导入多个类或接口,那么就并列显式多个import语句即可 4.举例:可以使用java.util.*的方式,一次性导入util包下所的类或接口。 5.如果导入的类或接口是java.lang包下的,或者是当前包下的,则可以省略此import语句。 6.如果在代码中使用不同包下的同名的类。那么就需要使用类的全类名的方式指明调用的是哪个类。 7.import static组合的使用:调用指定类或接口下的静态的属性或方法 (了解) 8.如果已经导入java.a包下的类。那么如果需要使用a包的子包下的类的话,仍然需要导入。
16. 一 维数组
16.一数组的概念
数组是多个相同数据类型的组合 说明:数组中的元素既可以是基本数据类型,也可以是引用数据类型,他的默认值和成员变量的默认值一样
16.2 一维数组的声明
String [] args; //建议这样写 String args[] ; //不建议这样写
16.3 一维数组的初始化
静态初始化,就是在声明的时候赋值
String [] names=new []{"1","2"} String [] names = {"aa","bb","cc"};//这种声明和赋值不能分开写
动态初始化通过数组的下标赋值
16.4 数组的长度 length
names.length; 可以用来返回数组的长度
16.5 一维数组的遍历
for (int i = 0; i < citys.length; i++) { System.out.println(citys[i]); }
16.6 一维数组的内存分析
16.7 冒泡排序
-
排序思想
-
相邻两元素进行比较,如有需要则进行交换,每完成一次循环就将最大元素排在最后(如从小到大排序),下一次循环是将其它的数进行类似操作。
/** * 冒泡法给整型数组排序,如果flag 为 true 那么就是升序排序。否则就是降序。 * @param args * @param flag */ public static void sort(int [] args , boolean flag){ if( flag ){ for(int i = 0 ;i < args.length-1 ;i++){ for(int j = 0 ;j < args.length - 1-i;j++){ if(args[j] > args[j + 1]){ int temp = args[j]; args[j] = args[j+1]; args[j+1] = temp; } } } }else { for(int i = 0 ;i < args.length-1 ;i++){ for(int j = 0 ;j < args.length - 1-i;j++){ if(args[j] < args[j + 1]){ int temp = args[j]; args[j] = args[j+1]; args[j+1] = temp; } } } } }
-
17. 二维数组
17.1 二维数组概述
多维数组 : 二维数组
二维数组 : 二维数组的元素是 一维数组。
说明 :二维数组的元素的默认值为null (二维数组的元素为一维数组,一维数组属于引用数据类型)
17.2二维数组声明和初始化
String [1][2】 persons //建议这么写
String persons[1][2】//不建议这么写
静态初始化声明的时候赋值
String [][] persons =new String[][] { { "小苍", "110" }, { "小泽", "119" }, { "小泷", "911" } ; int [][] a ={{1,2},{2,3}};
动态初始化
//声明一个二维数组。有三个元素,每个元素的长度为2
String [][] persons = new String[3][2]
```java
int a=new int3;int b=new int{{1,2},{2,3}} ```
//给二位数组中的每一个元素赋值为一个一维数组
String [][] persons = new String [3][];
persons[0] = new String[3];
person[1] = new String[4];
person[2] = new String[5];
17.3二维数组的默认值
二维数组元素的默认值为null
17.4.二维数组的属性
length 返回第二维的长度
17.5 遍历二位数组
for (int i = 0; i < aa.length; i++) { for (int j = 0; j < aa[i].length; j++) { System.out.println(aa[i][j]); // 遍历的是二维数组中元素(一维数组)的元素 } }
17.6 二位数组的内存分析图
18 Arrays工具类常用方法
19数组常见异常
20. 可变形参
可变形参 的底层就是数组实现的 格式 类型 ... 名称 所以在方法重载的时候 1.如果这两个参数名称相同那么构成不了重载 2.可变形参 只能写在最后一个。参数,如果写在第一个。 3. 可变形参的 形参个数可以是任意 4. 的底层就是数组实现的所以也可以给他传数组
20.类的特性2 继承
继承的好处
1.减少了代码的冗余性,提高了代码的复用性
2.更好的扩展性
3.为之后的多态提供了前提格式
A extends B 说明 1.如果子类成了父类, 那么就拥有了父类的属性和方法(不认为父类中的构造器可以被继承) 2.一个类只有一个父类。但是一个父类可以有多个子类 3.子类继承父类。不能直接调用父类的私有化属性。只能通过get和set等公共的方法来调用 4.父类是一个相对的概念。父类。分为直接父类和间接父类。 子类同样继承间接父类的成员和方法
21.方法的重写
1 说明:
1.子类继承父类以后,子类可以对父类中的方法进行重写(覆盖,覆写)。
通过子类对象进行调用方法,实际上调用的是子类中重写的父类中的方法。
权限修饰符 返回值类型 方法名(形参列表){
方法体; }
2.细节(子类重写的方法 父类中被重写的方法) 1.子类重写的方法和父类被重写的方法的方法名和形参列表必须一样。 2.子类重写的方法的权限修饰符不小于父类被重写方法的权限修饰符。 3.子类重写的方法的返回值类型不大于父类被重写方法的返回值类型(父类被重写方法的返回值类型和子类重写方法的返回值类型必须有子父类关系才能)。 4.父类被重写方法的返回值类型如果是void 子类重写方法返回值类型也只能是void 5.父类被重写方法的返回值类型 double 子类重写方法返回值类型int (不可以的,只能是相同的) 6.子类方法抛出的异常不能大于父类被重写方法的异常
3.注意 : 1.如果父类中的方法的权限修饰符是private,那么我们不认为这个方法可以被子类重写()。 2.子父类中同名的方法(非重写)须同时为static的,或同时为非static的
22. super关键字
super调用属性和方法
-
super可以用来调用父类中的 : 属性,方法,构造器。
-
直接写属性名或者方法名 默认是用 this.来调用
-
this.是先调用自身的。如果自生没有的话就调用父类的。如果父类也没有就报错。
-
super 是直接去父类里面找。如果需要调用父类被子类重写的方法就要用到supe
super 调用构造器
格式 : super(形参列表) : 调用父类中指定的构造器
注意: 1.super(形参列表)只能放在子类构造器的首行 2.在子类同一个构造器中只能有一个super(形参列表) 3.在子类中,super(形参列表) this(形参列表) 只能存在一个,因为这两个都要写在第一行 4.在子类的构造器中如果没有显示的调用super(形参列表)和this(列参列表) 那么默认调用的是 super() - 父类的空参构造器 5.子类中一定会调用父类的构造器
package com.lw.java2; /* * * 关键字super 调用父类中的成员 * super可以用来调用父类中的 : 属性,方法,构造器。 * * 直接写属性名或者方法名 默认是用 this.来调用 * this.是先调用自身的。如果自生没有的话就调用父类的。如果父类也没有就报错。 * super 是直接去父类里面找。如果需要调用父类被子类重写的方法就要用到super * * super 调用构造器 * 格式 : super(形参列表) : 调用父类中指定的构造器 * 注意: * 1.super(形参列表)只能放在子类构造器的首行 * 2.在子类同一个构造器中只能有一个super(形参列表) * 3.在子类中,super(形参列表) this(形参列表) 只能存在一个因为这两个都要写在第一行 4.在子类的构造器中如果没有显示的调用super(形参列表)和this(列参列表) 那么默认调用的是 super() - 父类的空参构造器 * 5.子类中一定会调用父类的构造器 */ public class TestSuper { public static void main(String[] args) { Animal animal = new Animal(); animal.say(); Dog dog = new Dog(); dog.say(); } } class Animal{ public Animal() { // TODO Auto-generated method stub System.out.println("我是amimal中的空参构造器"); } public void say(){ System.out.println("啊啊"); } } class Dog extends Animal{ public Dog(){ } public void say(){ super.say(); System.out.println("汪汪汪"); } }
22.子类的实例化过程(了解)
结果
子类继承了父类以后,那么子类就拥有了父类的属性和方法,通过子类对象就可以调用父类的属性和方法
过程
通过子类构造器来调用父类构造器......Object类的构造器。进而将这些类的信息加载到jvm内存中。所以可以调用父类的属性和方法。
注意
虽然调用了其他类的构造器但是自始至终我们只创建了一个对象
23.类的第三特性 ------------多态
概念
事物的多种形态
多态的体现
1.广义上的体现:
①方法的重写,重载。 ②子类对象的多态性
2.狭义上的体现: ①子类对象的多态性
子类对象的多态性:父类对象的引用指向子类对象
多态的前提
多态必须要有继承。和重写。
多态代码
//有三个类。Man和women继承了person //person中有show方法,Man和Women中重写了show方法。man中有smoking方法 //women中有shopping方法 public static void main(String[] args){ //父类的引用指向子类的对象 Person p = new Women();
虚拟方法调用
//调用的是Women中的show方法。因为这本来是一个women对象 p.show(); //注意p不能调用shopping方法。因为我们现在把女人当人看了。多态的情况下不能调用子类特有的方法。 //属性没有多态。如果是person中和woman中都有一个name属性。那么用p.name调用的是person中的name
如何调用子类特有的方法
//可以就可以强转成Women对象,因为p本来就是一个Women对象。 //这样就可以调用Woman中特有的方法了,向下转型 : 使用强制类型转换符 :(需要强转成的类型) Women w = (Women)p; }
多态的运行时异常
//运行时发生异常 : 创建的对象是一个女人,转成一个男人就会发生 ClassCastException Man m = (Man)p; m.smoking(); Person p2 = new Man(); Women wo = (Women)p2;
使用instance运算符 避免运行时异常
//instanceof运算符 左边是对象。右边是类型。假如左边的对象是右边的类型,那么返回true //否则返回 false if(p instanceof Women){ System.out.println("人家是一个小女生了"); Women w2 = (Women)p; w2.shopping(); }else{ System.out.println("我去,是一个男人耶"); }
instanceof运算符细节
增加一个Creature生物类。让Person类来继承他
//子类对象跟本类或者父类对象做运算返回true 就像 女人是一个人。是对的 //但是反过来就是错的。 那 人是女人这句话就有问题了 Creature c = new Women(); Person person = (Person)c; person.show(); //创建的具体的对象是谁,那么调用的就是谁 System.out.println(c instanceof Women); //true System.out.println(c instanceof Person); //true System.out.println(c instanceof Creature); //true Creature c2 = new Creature(); System.out.println(c2 instanceof Women); //false System.out.println(c2 instanceof Person); //false System.out.println(c2 instanceof Creature); //true
多态的应用
package com.lw.java; /** * 多态的应用场景 * @author Administrator * */ public class PhoneTest { public static void main(String[] args) { new PhoneTest().userPhone(new AndroidPhone()); new PhoneTest().userPhone(new IPhone()); } /** * 利用多太的特性创建出一个方法,可以使用所有的手机 * @param p */ public void userPhone(Phone p){ p.call(); p.sendMessage(); } } class AndroidPhone extends Phone{ @Override public void call(){ System.out.println("我是Android手机我能打电话"); } @Override public void sendMessage(){ System.out.println("我是Android 手机我能发短信"); } } class IPhone extends Phone{ @Override public void call(){ System.out.println("我是iphone手机 我能打电话"); } @Override public void sendMessage(){ System.out.println("我是iPhone手机我能发短信g"); } } class Phone{ public void call(){ System.out.println("我是手机 我能打电话"); } public void sendMessage(){ System.out.println("我是手机我能发短信"); } }
24. Object 类
1.Object类是所有类的直接或间接父类
2.Object类中有11个方法。其中有三个方法是重载的
3.一个类如果没有显现的继承其他类,那么他默认继承于object类。
4.Object类只有一个空参的构造器
25. equals方法
### Object类中的equals
//Object中的equals方法 就和 == 是一样的 判断地址值是否相同 public boolean equals(Object obj) { return (this == obj); }
很多类都重写了equals方法
String Date 等
如果自定义的类中没有重写equals方法
那么就调用了继承Object类中的equals方法。就比较地址值了
但是我们想要比较的的。内容是否相同。所有一般的自定义类中都重写了 equals方法
注意: [面试题] == 和equals的区别
== 是一个运算符
基本数据类型:比较的是具体的数值
引用数据类型 比较的是对象的地址值。
equals 是Object类中的一个方法。
一般类要重写这个方法。来比较两个对象的内容是否相同。
25.toString 方法
Object 类中的toString 方法
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); } //String,Date等类,都重写了toString方法。 // 在自定义类中,如果没有重写toString方法那么输出的是对象的地址值。 //往往我们调用toString方法时都是需要输出对象中属性的内容。所以自定义类中需要重写toString方法
public String toString(){ }
26.static关键字
概述
static 可以用来 修饰属性 ,方法,内部类,代码块
变量按照位置来分 可以分为 成员变量 vs 局部变量
成员变量可以分为 成员变量 vs 类变量
static修饰属性
-
static修饰的属性。被存放在方法区中的静态域。
-
static修饰的属性。整个类共享一个。
-
static修饰的属性。随着类的加载而加载。实例变量随着对象的创建而创建
-
类的加载(先从方法区去找类的信息。如果没有就加载类的信息。到方法去。类只会被加载一次)
-
类变量的调用 类名.类变量名。对象.类变量名
static修饰方法
1.静态方法随着类的加载而加载
2.静态方法的调用。通过类名.方法名。对象名.方法名
3.静态方法中。只能调用静态属性。不能调用非静态属性。
4.类的加载优先于对象的创建
5.静态方法中不能用this和super
27.类的加载过程
1.先去方法区中找,看看有没有类的信息。如果有就不加载。没有就先加载类信息。
2.加载的时候将静态变量,放入静态域。
3.可以通过类名.类变量名对 类变量进行赋值或者调用。
创建对象
-
1.先去方法区查看有没有当前类的信息,如果没有进行 类加载
-
2.类加载时,如果类中有类变量,会将类变量放入静态域中
-
3.根据类的信息在堆中创建类的对象
28.单一设计模式
package com.lw.java1; public class SingleLetonTest { public static void main(String[] args) { System.out.println(Person1.getPerson()); System.out.println(Person1.getPerson()); System.out.println(Person1.getPerson()); System.out.println(Person2.getPerson()); System.out.println(Person2.getPerson()); System.out.println(Person2.getPerson()); } } /* * 单例设计模式目的 : 在整个项目中,对于当前类有且只有一个对象。 */ //饿汉式 一开始就创建对象 /* * 1.私有化构造器。 * 2.创建自身的静态变量 * 3.提供外界的获取方法。 */ class Person1{ private Person1(){} static Person1 p = new Person1(); public static Person1 getPerson(){ return p; } } //懒汉式. /* * 自己先不创建对象。之后才创建 * 1.私有化构造器 * 2.定义自身变量 * 3.给出提供外界获取的方法 * 3.1判断自身的变量是否为空 * 3.2如果为空则new 一个 返回 * 3.3否则直接返回之前创造过了的变量 */ /* * 懒汉式饿汉式比较 * * 饿汉式 是线程安全的 * 懒汉式 是线程不安全的。延迟了对象创建的时机。 */ class Person2{ private Person2(){} static Person2 p; public static Person2 getPerson(){ if(p == null){ p = new Person2(); return p; }else { return p; } } }
29.代码块
package com.lw.java2; /* * 代码块: * 静态代码块 * 1.随着类的加载而加载,只会执行一次 * 2.只能调用静态方法和类变量 * 3.如果有多个是按照写的顺序从上到下来执行的。 * 代码块 * 1.随着对象的加载而加载。对象创建一次,就执行一次 * 2.能调用静态成员,静态方法,非静态成员,非静态方法 * 3.如果有多个非静态代码块,那么执行的顺序是从上到下依次执行 * 4.非静态代码块的加载优先于构造器的调用。 * 代码赋值的顺序 * 默认值 -》显示赋值/代码块(这两个谁先写,谁先执行。)-》构造方法-》 */ public class BlockTest { public static void main(String[] args) { new Person(); new Person(); new Person(); } } class Person{ int a = 2; static int b1 = 3; { say(); a = 5; b1 = 5; System.out.println("我是非静态代码块1,我每次创建对象都会执行"); } { say(); a = 5; b1 = 5; System.out.println("我是非静态代码块2,我每次创建对象都会执行"); } public static void say(){ System.out.println("哈"); } public Person() { // TODO Auto-generated constructor stub System.out.println("我是构造方法"); } static { say(); b1 = 7; System.out.println("我是静态代码块1,我在加载类的时候执行,我只能调用静态成员,和静态方法"); } static { say(); b1 = 7; System.out.println("我是静态代码块2,我在加载类的时候执行,我只能调用静态成员,和静态方法"); } }
29 final关键字
package com.lw.java3; /* * final关键字 * 修饰类:这个类不能被继承 * * 修饰方法:这个方法不能被重写 * * 修饰变量:一定要为这个变量赋一次值。也只能赋一次值 * final修饰的属性可以赋值的方式有 : 显示赋值,代码块赋值, * 构造器赋值(必须保证每个构造器都能给final修饰的属性赋上值) */ public class FinalTest { } class A{ private final int b=1; public A(){ } public final void say(){ } } class B extends A{ }