面向对象
新建对象的五种方式
1. 使用new关键字 2. 使用反射,调用newInstance
3. 使用clone方法 4. 使用序列化与反序列化
5. 动态代理(Proxy类和CGLIB)
什么是对象:在Java中,万事万物皆对象,每个对象都拥有属于自己的特定属性和行为。
面向对象(oop)的特点:
封装,隐藏内部实现,只暴露公共行为
继承,提高代码的重用性 (private修饰的成员变量和构造方法不能被调用)
多态,体现现实生活中相似对象的差异性
(抽象,抽取现实世界中相似对象的共同点)
面向对象和面向过程的区别
面向过程:面向功能划分软件结构、自顶而下、最小的子系统是方法、制约了软件的可维护性和可扩展性;
面向对象:把软件系统看成各种对象的集合、系统结构较稳定、子系统相对独立、软件可重用性、可维护性和可扩展性强。
——————————————————
类和对象
- 类是Java的核心,所有的Java程序都是基于类的,它定义了对象的属性和行为。定义一个类表示定义了一个功能模块。成员变量和方法是类的主要组成部分,成员变量描述的是对象的属性,成员方法描述的是对象的行为。
- 通过new关键字创建一个对象之后,如果对象存在有成员变量,系统就会为其自动分配一个初始值;
- 一个Java源文件中可以定义多个类,但最多只能定义一个public的类,并且public类的类名必须与源文件名一致。一个文件中可以只有非public类,而且这些类的类名可以跟Java源文件名不同。
- 类和对象关系
类的主要组成部分是成员变量和方法,成员变量表示对象的属性,方法表示对象的行为;
类和对象关系:类是对象的集合,对象是类的实例,对象是对事物的抽象,类是对对象的抽象。
——————————————————
访问控制符
访问控制符可以限制外界对程序员定义的类、方法及变量的访问权限。
- Public访问权限最大,当前类、当前包、子孙类、其他包都可以访问
- protected可以访问当前类、当前包子孙类
- friendly/default(不写)可以访问当前类、当前包
- private只可以访问当前类
——————————————————
局部变量和全局变量
局部变量和成员变量区别
- 成员变量描述的是这个对象里的属性
- (new创建对象后,对象存在成员变量,系统会为其自动分配)
- 局部变量描述的是这个方法体内的属性
- (方法体里创建的,方法体外访问不到这个变量)
- 访问区别:
成员变量可以被public\protected\default\private\static\final修饰
局部变量可以被final修饰符修饰
成员变量有系统默认值
局部变量没有系统默认值,必须手动赋值,在声明后不为其赋初始值,系统不会为其分配初始值
——————————————————
方法
[修饰符] 返回值类型 方法名(参数列表)
{
语句序列:
}
方法体:方法头:
- 方法最多只能返回一个值;
- 方法头一般由方法名、参数列表、返回类型、方法修饰符和方法抛出的异常五部分组成。方法名可以是任何有效的标识符;
- 方法头定义了方法的性质,方法体定义了方法的具体内容;
- 方法体中如果指定了非void的返回值类型,方法中就必须包含一条return语句保证任何情况下都有返回数值,return语句后面不能跟任何表达式;
- 参数值是通过临时变量传递的。
方法的返回值
是指我们获取到的某个方法体中的代码执行后产生的结果!(前提是该方法可能产生结果)。返回值的作用是接收出结果,使得它可以用于其他的操作
按照方法的返回值和参数类型将方法分为下面这几种:
1、无参数无返回值的方法
public void f1() {
//......
}
// 下面这个方法也没有返回值,虽然用到了 return
public void f(int a) {
if (...) {
// 表示结束方法的执行,下方的输出语句不会执行
return;
}
System.out.println(a);
}
2、有参数无返回值的方法
public void f2(Parameter 1, ..., Parameter n) {
//......
}
3、有返回值无参数的方法
public int f3() {
//......
return x;
}
4、有返回值有参数的方法
public int f4(int a, int b) {
return a * b;
}
—————————————————
形参和实参区别
形参一般在定义方法或过程时声明的参数
实参程序运行中调用方法或过程时,传递给方法或过程的参数
静态方法和实例方法区别
- 调用方式:
在外部调用静态方法时,可以使用 类名.方法名 的方式,也可以使用 对象.方法名 的方式,一般建议使用 类名.方法名 的方式来调用静态方法;调用静态方法可以无需创建对象,而实例方法只有使用 对象.方法名 的方式;
- 访问类成员是否存在限制:
静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),不允许访问实例成员(即实例成员变量和实例方法),而实例方法不存在这个限制。
——————————————————
构造方法
- 数据方法名和类名相同;不能有返回值,不用void修饰;
- Public+类名;可以重载不可以重写;
- 在类的实例化对象(创建对象)的时候,初始化成员变量
- 构造函数作用:有参初始化,引用实例化
——————————————————
重载、重写
重载(Overload)和重写(Override)的区别。
- 重载是编译时多态,重写是运行时多态
- 重载:同名不同参。在同一个类或父子类,重载中参数列表至少满足个数不同、类型不同、顺序不同中的一个条件
- 重写:重写父类方法,同名也同参。发生在父子类之间,参数列表完全相同:个数相同、类型相同、顺序相同,子类的返回值不能比父类的返回值范围大,子类方法抛出的异常不能比父类方法抛出的异常范围大,父子类方法不能使用static修饰。
方法的重载(overload): 在同一个类中,有方法名一样,但是参数列表不一样的多个方法。
方法的重写(override): 在子父类中,出现除了方法体其他都一样的方法,此时子类中这个方法称为方法的重写。
子类构造函数可以通过 super(参数1, 参数2) 调用父类的构造函数
——————————————————————————————————————
封装
包
为便于管理大型软件系统中数目众多的类,解决类的命名冲突问题,Java引入了包机制(package),提供了类的多重命名空间。
利用import语句导入指定的Java类。如果将一个类打包,当程序需要使用该类时,必须使用该类的全类名(即:包名+类名,例如:com.bw.MyClass),Java才会找到这个类。
package com.bw; 表示:该文件中所有的.java文件位于【项目名称\com\bw】目录下。
JDK(JavaDevelopmentKit)中主要的包
- Java.lang:包含一些Java语言的核心类,如:String、Math、Integer、System和Thread,提供常用功能
- java.awt:包含了构成抽象窗口工具集的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)
- java.net:包含执行与网络相关的操作类
- java.io:包含能提供多种输入/输出功能的类
- java.util:包含一些使用工具类,如:使用与日期相关的函数等
——————————————————
静态变量
实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。
静态变量和实例变量的区别
在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加。
在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。
package test;
public class Count {
public static int shu = 0; //静态成员变量
public void add() {
Count.shu++; //通过 类名. 来访问静态的成员
}
}
package test;
public class TestCount {
public static void main(String[] args) {
Count c1 = new Count();
c1.add();
Count c2 = new Count();
c2.add();
System.out.println(Count.shu);
}
}
——————————————————
封装
封装就是信息隐藏,是指将数据及数据的操作封装在一起,使其构成一个不可分割的实体,数据被保存在实体的内部,尽可能的隐藏内部的细节,只保留一些对外的通道使之与外部发生联系。系统的其他对象只能通过包裹在数据外面的已经授权的操作来与这个封装的对象进行交流。
- 利用private修饰符将需要隐藏的属性,隐藏起来 对外提供,getter,setter,方法 ;
- 成员变量私有化private 创建get/set 方法: get只读属性,set只写属性;
- 被private修饰的成员,只能在类的内部访问;
- this可以直接访问类中的变量;
- 外部接口代码快捷方法;
- 生产 set和get方法,快捷键Alt+shift+s +“r”。
封装的特点
- 把类的属性隐藏,提供公共方法对其访问
- 提高了代码的复用性
- 提高了代码的安全性
案例:类和对象:
需求分析:将小汽车改装成3个轮子的黑色车。
定义以下两个类:
1:汽车类。
2:汽车修理厂。
汽车类有以下变量和方法:
String name(汽车名称)
String color(汽车颜色)
int numTyre(汽车车轮个数)
run()方法:输出车的名称,颜色,车胎数,并加上“跑起来了”这句话。
汽车修理厂有如下需求:
String name(车厂名称)
String addr(车厂地址)
public Car repairCar(Car c) 修车方法(将车轮数修改为3)
创建测试类,调用修车方法。
package 封装;
import java.util.Scanner;
public class Car {
//属性:车牌号、车型、颜色、日租金、载重量
private int day; // 租赁天数
private String number; // 车牌号
private String type; // 车型
private String color; // 颜色
private int weight; // 载重量
private double money; // 应付金额
public Car(String number, String type, String color, int weight, double money) {
super();
this.number = number;
this.type = type;
this.color = color;
this.weight = weight;
this.money = money;
}
private String name; // 租车人
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
// 方法 租赁
public void rent() {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入租车人姓名:");
String name = scanner.next();
System.out.print("请输入租赁天数:");
int day = scanner.nextInt();
System.out.println("租赁信息");
System.out.println("车牌号:" + number);
System.out.println("车型:" + type);
System.out.println("颜色:" + color);
System.out.println("载重量:" + weight);
System.out.println("租车人:" + name);
System.out.println("租赁天数:" + day);
System.out.println("应付金额:" + money);
}
}
package 封装;
public class TestCar {
public static void main(String[] args) {
Car car = new Car("吉ANB999", "红旗", "绿色", 100, 1111111);
car.rent();
}
}
——————————————————————————————————————
继承
- Java中使用extends关键字实现类的加载机制称之为继承,子类自动拥有了基类(也叫父类,superclass)的所有成员,即成员变量和成员方法。
- 如果父类中变量定义成了private私有变量,则在子类中是不可以调用的,只能在父类的方法中调用,子类和其他类都不可以。
- Java只支持单继承,不支持多继承,即:一个子类只能有一个基类(父类),但是一个基类可以有多个子类;
- 子类对象包含父类对象,父类有的子类有,子类有的父类不一定有;
- 静态方法是不可以继承的。
extends 后是父类
This 访问本类的成员变量 this.方法名() 调用同类方法
super访问父类的成员变量 super.方法名() 调用父类方法
例:
//自行车类
public class Bike {
public int wheels = 2; //轮子数量
public void run(){
System.out.println("自行车都能跑");
}
}
//变速自行车类
public class RaceBike extends Bike {
public int gear = 2; // 齿轮个数
public void speedUp() {
System.out.println("变速自行车可以加速");
}
public void speedDown() {
System.out.println("变速自行车可以减速");
}
}
//测试类
public class Test {
public static void main(String[] args) {
RaceBike bike = new RaceBike();
int wheels = bike.wheels; //获取父类的成员变量wheels
int gears = bike.gear;
System.out.println("变速车的轮子数量是:" + wheels);
System.out.println("变速车的齿轮数是:" + gears);
bike.run(); //调用父类的跑的方法
bike.speedUp();
bike.speedDown();
}
}
——————————————————————————————————————
多态
动态绑定是指在运⾏期间,判断所引⽤对象的实际类型,根据其实际的类型调⽤相应的⽅法,多态即:⼀个对象具有多种状态的⾏为。
多态的3个必要条件
- 要有继承
- 要有重写
- 父类的引用指向子类的对象
对象转型
向上转型:父类引用指向子类对象
向下转型:子类引用指向父类对象,需要强制转换
例:
需求分析:
木兰从军:女扮男装替父从军,得胜回朝换回女儿神梳妆打扮。需要3个类,分别是父亲类Father.java(属性:name、age方法:fight),女儿类Daughter.java(方法:fight、dressup),还有一个测试类Test.java
//父类Father.java
package test;
public class Father {
public String name;
public int age;
public void fight(){
System.out.println("我是花弧我要去打仗");
}
}
//子类Daughter.java
package test;
public class Daughter extends Father {
@Override
public void fight() {
System.out.println("姓名:"+name);
System.out.println("年龄:"+age);
System.out.println("我是女儿,我替父从军");
}
public void dressup(){
System.out.println("姓名:"+name);
System.out.println("年龄:"+age);
System.out.println("我是女儿,我要画一个美美的妆");
}
}
//测试类Test.java
package test;
public class Test {
public static void main(String[] args) {
// 女扮男装,转型父亲的角色去征兵打仗
Daughter mulan = new Daughter();
mulan.name = "花木兰";
mulan.age = 18;
//花木兰替父从军(向上转型)
Father huaHu = mulan;
mulan = null;
huaHu.fight();; // 征兵打仗
// 得胜回朝
System.out.println("****得胜回朝*****");
// 之前转型父亲角色的花木兰重新转型为女儿角色(强制向下转型)
mulan = (Daughter) huaHu;
huaHu = null;
mulan.dressup(); // 梳妆打扮
}
}
——————————————————————————————————————
Super关键字
Super关键字,可以用来子类调用父类的成员用,它包括调用父类的public、protected修饰的变量方法。
- 调用父类的方法: super.父类的方法;
- 同时super也可以调用父类的构造方法,但是父类中构造方法用private修饰时,不能有子类去继承;
- 子类可以没有构造方法,他会自动调用父类的构造方法;
- 在子类中可以调用父类的构造方法,super必须放在子类构造方法的首句。
——————————————————————————————————————
Object类
Object类是所有Java类的根基类,如果在类的声明中未使用extends关键字指明基类,则默认基类为Object类。
public class Person {
}
等价于
public class Person extendsObject {
}
——————————————————
toString方法
- Object类中定义有 public String toString() 方法,其返回值是String类型,描述当前对象的所有信息
- 在进行String与其他类型数据的连接操作时(如:System.out.println("info:" + person);),将自动调用该对象的toString()方法
- 可以根据需求在用户自定义类型中重写toString方法
例:
需求分析:定义Person类,Person类中有私有成员变量名称(name)、年龄(age),定义一个有参构造器用于初始化成员变量,重写toString方法返回用户信息(包括姓名和年龄);定义一个测试类,在测试类中实例化Person对象并且调用Person对象的toString方法,在控制台输出用户信息。
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "我叫" + name + "几年" + age + "岁了";
}
}
public class Test {
public static void main(String[] args) {
Person p = new Person("李雷", 18);
String info = p.toString();
System.out.println(info);
}
}
——————————————————————————————————————
equals方法
- Object类中定义有 public boolean equals(Object obj) 方法,提供判断定义对象是否相等的逻辑
- Object的 equals 方法定义为:x.equals(y) 当x和y是同一个对象的引用时返回true否则返回false
- JavaSDK提供的一些类,如String,Date等,重写了Object类的equals方法,调用这些类的equals方法,x.equals(y),当x和y所引用的对象是同一类对象且属性内容相等时(并不一定是相同对象),返回true否则返回false
- 可以根据需要,在用户自定义类型中重写equals方法
例:
需求分析:定义一个Dog类,Dog类中有成员变量名称(name)、年龄(age),定义一个有参构造器用于初始化成员变量,定义一个Dog数组,数组中有7个元素,分别是:金毛1岁,萨摩耶1岁,博美2岁,金毛2岁,金毛1岁,博美3岁,博美1岁;现重写Dog类中的equals方法,判断:只要Dog的名称和年龄相同,则表示是同一条狗。编写一个测试类,控制台输出相同的金毛狗的个数
public class Dog {
public String name;
public int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {// Object obj = dog;
if(obj instanceof Dog){
Dog dog = (Dog) obj;
if(dog.name.equals(this.name) && dog.age == this.age){
return true;
}
}
return false;
}
}
@Test
public void test(){
Dog[] arr = new Dog[7];
Dog dog1 = new Dog("金毛", 1);//
Dog dog2 = new Dog("薩摩耶", 1);
Dog dog3 = new Dog("博美", 2);
Dog dog4 = new Dog("金毛", 2);
Dog dog5 = new Dog("金毛", 1);//
Dog dog6 = new Dog("博美", 3);
Dog dog7 = new Dog("博美", 1);
arr[0] = dog1;
arr[1] = dog2;
arr[2] = dog3;
arr[3] = dog4;
arr[4] = dog5;
arr[5] = dog6;
arr[6] = dog7;
int cnt = 0;
for(int i=0; i<arr.length; i++){
for(int j=0; j<arr.length; j++){
if(arr[i].equals(arr[j])){
cnt ++;
}
break;
}
}
System.out.println("相同狗的个数是:" + cnt);
}
——————————————————————————————————————
final关键字
final修饰成员变量
- 引用变量不能重新赋值,但是引用指向的对象的内容可以改变
- 修饰类则该类不能被继承
- 修饰方法则该方法不能重写
- 修饰变量则赋值后不能改变
//final修饰方法
class A{
final void test(){
}
}
//final修饰成员变量
public class Test{
//final关键字修饰的成员属性称之为常量
public final String ID_CARD="220102200005062156";
}
final、 finally、finalize的区别。
- final 用于修饰类、方法、变量,修饰类不能继承,修饰方法不能重写,修饰变量赋值之后不能改变。内部类要访问局部变量,局部变量必须定义成final类型;
- finally是异常处理语句结构的一部分,表示总是执行,用来释放资源;
- finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。JVM不保证此方法总被调用。
——————————————————————————————————————
笔记内容来源:JavaGuide以及大坏蛋^_^的博客_优快云博客-Java基础,Linux,SpringBoot+领域博主