Java方法
理解方法的本质以及作用;
掌握方法的定义;
[修饰符列表] 返回值类型 方法名(形式参数列表){
方法体;
}
掌握方法如何调用;
理解栈数据结构;
理解方法执行过程中内存是如何变化的;
压栈,先进后出;
掌握方法的重载机制;
** 什么是方法重载呢?**
***重载(overload)是指在一个类中定义多个同名的方法,但要求每个方法具有不同的参数的类型或参数的个数。调用重载方法时,Java编译器能通过检查调用的方法的参数类型和个数选择一个恰当的方法。方法重载通常用于创建完成一组任务相似但参数的类型或参数的个数不同的方法。调用方法时通过传递给它们的不同个数和类型的实参来决定具体使用哪个方法。 ***
案例*
public static void main(String[] args) {
int x1 = 10;
int x2 = 20;
int retValue1 = sum(x1 , x2);
System.out.println(x1 + "+" + x2 + "=" + retValue1);
long y1 = 10L;
long y2 = 20L;
long retValue2 = sum(y1 , y2);
System.out.println(y1 + "+" + y2 + "=" + retValue2);
double z1 = 10.0;
double z2 = 20.0;
double retValue3 = sum(z1, z2);
System.out.println(z1 + "+" + z2 + "=" + retValue3);
}
public static int sum(int a , int b){
return a + b;
}
public static long sum(long a , long b){
return a + b;
}
public static double sum(double a , double b){
return a + b;
}
掌握方法递归算法。
递归:就是自己调用自己,然后到达一定条件然后跳出去;
Java面向对象
面向对象三大特征;
● 封装(Encapsulation)
● 继承(Inheritance)
● 多态(Polymorphism)
对象是类的实例化:
这是一个实体类;
package com.hao.se;
/*
*@hao
*
*
*
*/
public class Students {
String name;
int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Students{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package com.hao.se;
/*
*@hao
*
*
*
*/
public class OOP {
public static void main(String[] args) {
Students s1=new Students();
s1.name="小明";
s1.age=23;
Students s2=new Students();
s2.name="小孩";
s2.age=18;
System.out.println("第一个创建的对象"+s1.toString());
System.out.println("第二个创建的对象"+s2.toString());
}
}
通过上面的实体类然后new出来下面的对象,来实例化;
对象在内存中情况
JVM
● 程序计数器:
概念:可以看做当前线程所执行的字节码的行号指示器。
特点:线程私有的内存
● java虚拟机栈(重点):
概念:描述的是java方法执行的内存模型。(每个方法在执行的时候会创建一个****栈帧****,用于存储****局部变量****表,操作数栈,动态链接,方法出口等信息。每个方法从调用直至完成的过程,就对应一个栈帧从入栈到出栈的过程。)
特点:线程私有,生命周期和线程相同。这个区域会出现两种异常:StackOverflowError异常:若线程请求的深度大于虚拟机所允许的深度。OutOfMemoryError异常:若虚拟机可以动态扩展,如果扩展是无法申请到足够的内存。
● 本地方法栈:
概念:它与虚拟机栈所发挥的作用是相似的,区别是java虚拟机栈为执行java方法服务,而本地方法栈是为本地方法服务。
特点:线程私有,也会抛出两类异常:StackOverflowError和OutOfMemoryError。
● java堆(重点):
概念:是被所有线程共享的一块区域,在虚拟机启动时创建。
特点:线程共享,存放的是****对象实例****(所有的对象实例和数组),GC管
理的主要区域。可以处于物理上不连续的内存空间。
● 方法区(重点):
概念:存储已被虚拟机加载的****类信息、常量、静态变量****,即时编译器编译后的代码等数据。
特点:线程共享的区域,抛出异常OutOfMemory异常:当方法区无法满足内存分配需求的时候。
对象:
对象的构造方法:(Constructor)
public class Date {
int year; //年
int month; //月
int day; //日
//构造方法(无参数构造方法)
public Date(){
System.out.println("Date类无参数构造方法执行");
}
//构造方法(有参数构造方法)
public Date(int year1){
System.out.println("带有参数year的构造方法");
}
//构造方法(有参数构造方法)
public Date(int year1 , int month1){
System.out.println("带有参数year,month的构造方法");
}
//构造方法(有参数构造方法)
public Date(int year1 , int month1 , int day1){
System.out.println("带有参数year,month,day的构造方法");
}
}
this
this可以看做一个变量,它是一个引用,存储在Java虚拟机堆内存的对象内部,this这个引用保存了当前对象的内存地址指向自身,任何一个堆内存的java对象都有一个this,也就是说创建100个java对象则分别对应100个this。通过以上的内存图,可以看出“jack引用”保存的内存地址是0x1111,对应的“this引用”保存的内存地址也是0x1111,所以“jack引用”和“this引用”是可以划等号的。也就是说访问对象的时候jack.name和this.name是一样的,都是访问该引用所指向对象的name属性。
this指向“当前对象”,也可以说this代表“当前对象”,this可以使用在实例方法中以及构造方法中,语法格式分别为“this.”和“this(…)”。this不能出现在带有static的方法当中。
this
● this是一个引用,保存内存地址指向自己。
● this出现在实例方法中,谁调用这个实例方法,this就代表谁,this代表当前正在执行这个动作的对象。
● this不能出现在静态方法中。
● this大部分情况下可以省略,在方法中区分实例变量和局部变量的时候不能省略。
●“this(实际参数列表)”出现在构造方法第一行,通过当前的构造方法去调用本类当中其它的构造方法。
static
static是java语言中的关键字,表示“静态的”,它可以用来修饰变量、方法、代码块等,修饰的变量叫做静态变量,修饰的方法叫做静态方法,修饰的代码块叫做静态代码块。在java语言中凡是用static修饰的都是类相关的,不需要创建对象,直接通过“类名”即可访问,即使使用“引用”去访问,在运行的时候也和堆内存当中的对象无关。
有时你希望定义一个类成员,使它的使用完全独立于该类的任何对象。通常情况下,类成员必须通过它的类的对象访问,但是可以创建这样一个成员,它能够被它自己使用,而不必引用特定的实例。在成员的声明前面加上关键字static(静态的)就能创建这样的成员。如果一个成员被声明为static,它就能够在它的类的任何对象创建之前被访问,而不必引用任何对象。你可以将方法和变量都声明为static。static 成员的最常见的例子是main()。因为在程序开始执行时必须调用main() ,所以它被声明为static。
声明为static的变量称为静态变量或类变量。可以直接通过类名引用静态变量,也可以通过实例名来引用静态变量,但最好采用前者,因为后者容易混淆静态变量和一般变量。静态变量是跟类相关联的,类的所有实例共同拥有一个静态变量。
声明为static的方法称为静态方法或类方法。静态方法可以直接调用静态方法,访问静态变量,但是不能直接访问实例变量和实例方法。静态方法中不能使用this关键字,因为静态方法不属于任何一个实例。
public class Man {
//身份证号
int idCard;
//性别(所有男人的性别都是“男”)
//true表示男,false表示女
static boolean sex = true;
public Man(int idCard){
this.idCard = idCard;
}
//静态方法
public static void printInfo(){
System.out.println("-----" + (Man.sex ? "男" : "女") + "------");
}
}
public class ManTest {
public static void main(String[] args) {
//静态变量比较正式的访问方式
System.out.println("性别 = " + Man.sex);
//创建对象
Man jack = new Man(100);
//使用“引用”来访问静态变量可以吗?
System.out.println("性别 = " + jack.sex);
//对象被垃圾回收器回收了
jack = null;
//使用“引用”还可以访问吗?
System.out.println("性别 = " + jack.sex);
//静态方法比较正式的访问方式
Man.printInfo();
//访问静态方法可以使用引用吗?并且空的引用可以吗?
jack.printInfo();
}
}
直接看代码,来的快;
静态代码块
类{
//静态代码块
static{
java语句;
}
}
eg:
public class StaticTest01 {
//静态代码块
static{
System.out.println(2);
}
//静态代码块
static{
System.out.println(1);
}
//main方法
public static void main(String[] args) {
System.out.println("main execute!");
}
//静态代码块
static{
System.out.println(0);
}
}
继承
基本语法:
class 类名 extends 父类名{
类体;
}
案例:
父类:
public class Account { //银行账户类
//账号
private String actno;
//余额
private double balance;
//账号和余额的set和get方法
public String getActno() {
return actno;
}
public void setActno(String actno) {
this.actno = actno;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
}
子类:继承的父类(extends)
public class CreditAccount extends Account{ //信用账户类
//信誉度(特有属性)
private double credit;
//信誉度的set和get方法
public double getCredit() {
return credit;
}
public void setCredit(double credit) {
this.credit = credit;
}
}
主方法:
public class AccountTest {
public static void main(String[] args) {
CreditAccount act = new CreditAccount();
act.setActno("111111111");
act.setBalance(9000.0);
System.out.println(act.getActno() + "信用账户,余额" + act.getBalance() + "元");
}
}
覆盖:
方法的重载: 只要在同一个类当中,方法名相同,参数列表不同(类型、个数、顺序),即构成方法重载。
当程序具备哪些条件的时候,就能构成方法覆盖呢?
● 方法覆盖发生在具有继承关系的父子类之间,这是首要条件;
● 覆盖之后的方法与原方法具有相同的返回值类型、相同的方法名、相同的形式参数列表;
● 另外,在使用方法覆盖的时候,需要有哪些注意事项呢?
● 由于覆盖之后的方法与原方法一模一样,建议在开发的时候采用复制粘贴的方式,不建议手写,因为手写的时候非常容易出错,比如在Object类当中有toString()方法,该方法中的S是大写的,在手写的时候很容易写成小写tostring(),这个时候你会认为toString()方法已经被覆盖了,但由于方法名不一致,导致最终没有覆盖,这样就尴尬了;
● 私有的方法不能被继承,所以不能被覆盖;
● 构造方法不能被继承,所以也不能被覆盖;
● 覆盖之后的方法不能比原方法拥有更低的访问权限,可以更高(学习了访问控制权限修饰符之后你就明白了);
● 覆盖之后的方法不能比原方法抛出更多的异常,可以相同或更少(学习了异常之后就明白了);
● 方法覆盖只是和方法有关,和属性无关;
● 静态方法不存在覆盖(不是静态方法不能覆盖,是静态方法覆盖意义不大,学习了多态机制之后就明白了);
多态:
***多态就是“同一个行为(move)”作用在“不同的对象上”会有不同的表现结果 ***
多态(Polymorphism)属于面向对象三大特征之一,它的前提是封装形成独立体,独立体之间存在继承关系,从而产生多态机制。多态是同一个行为具有多个不同表现形式或形态的能力
多态存在的三个必要条件分别是:
● 继承
● 方法覆盖
● 父类型引用指向子类型对象
eg:就是继承了父类的方法,然后重写某一个方法变成自己的,然后多个子类将这个方法变成自己的;
Spuer
● super和this都可以使用在实例方法当中。
● super不能使用在静态方法当中,因为super代表了当前对象上的父类型特征,静态方法中没有this,肯定也是不能使用super的。
● super也有这种用法:“super(实际参数列表);”,这种用法是通过当前的构造方法调用父类的构造方法。
● this和super都是无法使用在静态方法当中的。
**super()的作用主要是:**第一,调用父类的构造方法,使用这个构造方法来给当前子类对象初始化父类型特征;第二,代码复用。
***JavaJava方法覆盖中的访问权限
Java访问覆盖(重写)的规则:***
● 子类方法签名必须和父类方法一致, 方法签名就是方法名与参数列表
● 子类方法的返回值类型可以和父类方法返回值类型一样, 也可以是父类方法返回值类型的子类型
● 子类方法的访问权限可以和父类方法访问权限相同,也可以比父类方法访问权限更宽泛(更大)
如果父类方法是public修饰,子类方法只能是public修饰
如果父类方法是protected修饰,子类方法可以protected/public修饰
● 子类方法的异常不能比父类方法的异常更大异常
Java中final关键字的作用
final关键字修饰类, 修饰字段, 修饰方法,修饰局部变量,修饰方法的形参
final修饰类,表示最终类, 不能被继承,不能作为父类存在
final修饰字段,在定义时必须显示初始化, 不能被修改, 一般与static同时使用,所有字母都大写,称为final常量
final修饰方法,不能被覆盖(重写)
final修饰局部变量, 一旦初始化就不能再修改, 注意final修饰引用类型变量,是指这个变量不能再指向 其他对象 , 可以修改它的字段值
final修饰方法形参, 在方法体中不能修改final参数的值
Java抽象类
当一个类的某个操作没法具体实现时,这个操作可以定义为抽象方法。
抽象方法使用abstract修饰的方法,只有方法的声明部分,没有方法体。
Java接口
/**
* 定义飞行接口
* 封装飞行功能
* @hao
*
*/
public interface Flyable {
//接口中的方法默认使用public abstract修饰
void fly();
}
然后下面为实现:
/**
* 定义鸟类
* 一个类实现了接口,需要重写接口中抽象方法
*
* @hao
*
*/
public class Bird implements Flyable {
@Override
public void fly() {
System.out.println("小鸟在天空中自由飞翔");
}
}
Java接口说明
1.类实现了某个接口,需要重写接口中的抽象方法,就具备了接口中定义的功能; 如果一个类实现了接口,没有重写接口中所有的抽象方法,这个类需要定义为抽象类。
2.一个类可以实现多个接口, 接口名之间使用逗号分隔, 这个类需要重写所有接口中所有的抽象方法。
3.接口也能继承,并且支持多继承, 在子接口中可以扩展接口的功能。
4.接口的内容在JDK8中, 只包含四部分: public abstract默认的方法, public static final默认的字段, public static静态方法, public default方法。
Java抽象类与接口的异同点
相同点
1.都可以定义抽象方法
2.都不能实例化对象
3.接口/抽象类的抽象方法都需要被重写
4.接口/抽象类中都可以定义 public static final字段, public static静态方法
不同点
1.意义不同
抽象类对类进行更高层级的抽象
接口是对功能的封装
2.定义方式不同
抽象类使用 abstract class定义
接口使用interface定义
3.内容不同
抽象类中除了可以定义抽象方法外, 还可以定义实例变量/实例方法/静态变量/静态方法,构造方法等普通类所有的成员。
接口中除了抽象方法外, 还可以定义public static final字段, public static方法,public default方法 。
抽象类有构造方法, 接口没有构造方法; 接口中可以使用default修饰方法,抽象类不能使用default修饰方法。
4.使用方式不同
抽象类一般作为父类存在, 需要子类通过extends继承。
接口需要通过类implements实现。
5.继承
类只支持单继承, 接口支持多继承
6.应用场景不同
如果仅仅是为了扩展类的功能,优先选择接口;
如果除了功能外,还需要保存不同的数据,选择抽象类, 抽象类中的抽象方法,需要在子类中重写, 抽象类可以约束所有的子类都具有某个功能。
*一些知识点以及图片来自于百度等