Java养成计划----学习打卡第四天
内容导航
Java入门到精通(打卡第四天)
学习内容
构造方法,static关键字;Java的继承与多态;抽象类,API应用(基本介绍)
内容管理
Java–构造方法
构造方法以及重载
构造方法我们之前已经说过,今天再说一次;构造方法要求方法名与类名一致,并且没有返回类型;这里我们就需要来辨识一下返回值以及返回值类型,返回值是方法返回的值,如果我们没有返回值呢,那就是说我们的这个方法前面的返回值类型是void;而没有返回值类型那就是我们只需要加访问权限和方法名;连void都不需要了呢!
这里我们之前知道我们创建一个类以后里面创建它的属性以及对应的方法,然后我们在同一个包下面去创建一个驱动类比如Main类,在这个Main类里面我们就可以定义所创那个类的对象;
package java_study;
public class Point2D{
protected float x;//在这个类中,这相当于我们C里面没有封装的全局变量
protected float y;
// public Point2D(float initialX,float initialY)//构造方法
// {
this.x = 1.0;
// x = initialX;
// y = initialY;
// }
public float getX()
{
return x;
}
public float getY()
{
return y;
}
}
这里我们就创建了一个Point2D类 ,类里面有两个对象x, y,但是我们在这里加了一个private就只能同一类访问,所以把它改成缺省或者protected;之后就可以被本包内的Main类访问了
package java_study;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Point2D pointone = new Point2D();
pointone.x = 2;
pointone.y = 3;
System.out.println(pointone.getX());
System.out.println(pointone.getY());
}
}
这里就涉及到我们即将接触的知识点就是我们不能乱用static,我编写代码时就是因为static用的不一致就提出警告⚠,所以我就没有使用static;
好了我们进入主题构造方法,我们说过这个方法与类名一致且没有返回值类型,那我们什么时候调用的呢,我们上面的函数已经演示了普通方法的调用,其实构造方法就是我们在创建对象时调用的;
Point2D pointone = new Point2D();//这里的Point2D()就是构造方法
构造方法一般用来做程序的初始化,我们说过this的用法,那就是调用类里面的对象;我们如果想要一个特定的值来初始化,就将其放在构造方法里面
比如我这里觉得所有的横坐标x都是从1.0开始变化的,所以就在构造方法里加一句this.x = 1.0;就可以了,下次程序再用,初值都是1.0了,而不是0.0;构造方法前面也可以和普通的方法一样可以使用之前的那四种访问权限private,public,protected和缺省,这里我们就要注意一般我们的构造方法的权限都是public,因为这个一般是创建对象时使用的,用其他的万一对象都创建不了怎么操作呢?
需要注意的是只要满足两点条件:类名一致,没有返回值类型都应该是构造方法,但是我们就必须要重载才可以,不然就会报错,我们就要让它们的参数列表不一样就可以了
比如我们这里构造方法里就可以使用
public Point2D(float x,float y)
{
this.x = x;
this.y = y;
}
//在Main类中,创建对象时
Point2D pointone = new Point2D(1.0,2.0);
这样子就会调用我们创建的第二个构造方法;这就是重载;如果我们使用了之后就会自动给赋值了,就是1.0和2.0;并且使用的new在堆中开辟的内存,所以是引用传递
通常情况下我们要么创建无参的构造方法,要么构建全参的构造方法,这里我们不需要自己来做这件事,使用eclipse来帮助我们,这里我们就单击右键,选择source,选择Generate constructor using Fileds—创建构造方法,就可以创建了;
创建的代码第一行有一个surper();这个我们后面再说,任何一个类都有一个构造方法,我们自己我们没写无参的构造方法,那么系统会自动赠送一个无参的构造方法;即使将所有的赋予一个0的初值
(这里我们使用ALT +/ 可以开启联想模式,这里不仅是属性和方法)输入main就可以自动将其联想出来 public static void main(Sting[] args);
static关键字
-
static的意思是静态的;是用来修饰成员变量和成员方法
-
一旦我们加了static,那么修饰的变量就是(静态变量,类变量),没被修饰的就是非静态方法或者实例方法;static修饰方法也就是类方法
-
静态变量和方法可以通过对象,也可以通过类名直接访问;而实例变量和方法只能通过对象访问,之前我们加了static,在Main类就可以直接Point2D来访问;就是可以直接通过Point2D.x = 1.0;这是可以访问的;
-
当变量被修饰为静态变量后,则该变量的值被所有成员共享;所以叫做类变量,一旦一个对象的属性值发生变化,所有的属性值都会i发生变化(举个例子,⚪这个类下面有很多对象,比如⚪A,⚪B之类的,但是⚪类的一个属性比如形状shape都是圆的;那么这个变量shape就应该是类变量,因为所有对象都是圆的,这也就是为什么可以直接类来访问,因为所有对象的该量的值是相同的,没有第二种可能,所以如果不同的对象有不同的值,那么就不能使用static;而我们的main方法是每一个对象都应该会具有的,所以就要使用static
-
在静态环境中不能使用非静态的属性与方法;加了static的方法的作用域就是一个静态环境,这里面不能出现任何非静态的方法或者变量,之前我在float x前没加static,但是在下面的方法里加了static,这时程序就在return x; 报错了;这就是因为静态环境中出现了非静态变量;我们的main方法里面也是静态环境,那就只能使用加了static的方法或者变量;但是在非静态的环境中时是可以使用静态的方法或者变量的
-
在静态环境中,不可以使用关键字this,super;我们说过就是使用本类的属性就是用this关键字;
静态代码块
就是类在刚被加载时,静态代码块里面就会被执行并且只执行一次,并且执行优先于构造方法
static
{
·········//代码;一般用来做初始化,在jdvc那里再讲
}
变量与this关键字
变量
- 成员变量: 定义在类里面的变量,称之为成员变量(像我们没有封装的C语言里面的全局变量)这个就是我们之前分析的那个类图的类里面的属性
- 局部变量:定义在方法里面的变量,称之为局部变量
它们的作用域不同,(判断依据:变量在哪个大括号里被定义,那就只能在哪个大括号里面使用)成员变量的作用域是整个类;而局部变量只是在所在的方法里;像for循环里面的循环变量的作用域也只是在那个大括号里;
它们的初始值不同;成员变量因为构造方法就会自动初始化;但是局部变量就没有初始值,就必须先赋予一个初始值,才可以使用;这里不初始化系统就会警告
this关键字
- 当局部变量与成员变量同名时,我们在另外一个类里访问时局部变量所在方法时,起作用的是局部变量,而成员变量在这个方法里不可见
如果我们一定要访问这个成员变量时,那我们就要使用这个this关键字;在方法里访问同名成员变量就在前面加this关键字;比如this.x;
- 注意:this关键字本质上时指当前对象(该方法是哪个对象调用的,则this就是指的是该对象)
System.out.println("pointone ==" + pointone);//这里我们知道对象创建都是在栈里面,对象变量存储的都是它们的在堆中的地址
//在之前的Point2D类里面的要调用的方法里来一句
System.out.println("this ==" + this);//那么这两句话所打印的都是相同的地址,前面可能不一样,但地址一定一样
import关键字
我们之前说过就是将其他的类导入的关键字,只是我们的类的路径要全一点;CTRL+ D删除;
import java.util.Scanner //但是我们其实我们不需要自己写,我们使用ALT +/就可以选择一个类,之后回车,系统就会自动将这句给加上
我们昨天还说过可以使用导入这个包所有类,使用* ,但是不建议用,昨天说过这个不影响执行的效率,但是我们会增加我们的程序的文件大小;还有就是会导致类名的错乱;比如在Java类库中,util中有一个Date类,但是在sql包中也有一个Date类,我们有的时候如果将整个包导入,就不知道我们是否错了,所以还是不要嫌麻烦,使用哪个类,就导入哪个类;
继承与多态
前面再讲解面向对象的时候我们已经提到过继承,但是浅尝辄止,今天再次深入了解一下继承和多态;我们知道Java是面向对象的语言,而面向对象就有几个特点那就是封装、继承、多态,封装我们已经充分见识了,就是将一个需求中的对象抽象化为类,然后将类再打包封装,以实现复杂的功能;
封装的书面定义就是:将属性和方法定义在类的里面,其他类不可以直接访问该类的方法与属性,而是要通过对象的方式简洁访问
而继承呢,就是我们之前说过的is-a的关系,是类之间的关系;举个例子:我们现在将动物抽象化为一个类,然后将🐕抽象化为一个类,那么动物类所具有的属性是不是🐕类都具有呢,这是当然,所以我们在Java中具体实现的时候难道要再重复定义一次吗?这当然不行,Java就是要努力避免代码的重复,那应该怎么解决呢,这个时候就用到了我们的继承
extends 关键字
在Java里面具体实现就用的是extends这个关键字,这里举个例子
//假如我们已经建立好了一个动物类
public class Aniaml{
·····
}
//现在我们要创建一个dog类了,它要继承Animal类
public class Dog extends Animal{
···
}
使用的方法就是酱紫的~
这里我们还是使用上面所说的那个类Point2D
package java_study;
public class SpcialPoint2D extends Point2D{
//我什么也没写,就用extends继承了Point2D类
}
这里就完美的继承了,那我现在再演示一下重写
package java_study;
public class SpcialPoint2D extends Point2D{
//我什么也没写,就用extends继承了Point2D类
@Override//重写前加上注解@override提示这是重写 ALT + /就可以联想
public float getX()
{
return 2*x;
}
}
然后我在Main类里调用方法输出的就是2*x了
- B类可以通过关键字extends与A类建立继承关系,从而自动获得A类中非私有的属性与方法,加了关键词private的就不行额,(private的权限就只是类内可见)继承的类叫做子类,被继承的叫做父类
- 子类继承父类后,也可以新增自己的属性与方法,子类就是special,父类就是general,当然就有自己的特色了
- 子类继承父类后发现给与的方法不适合怎么办呢?那么我们就要重写该方法,这里的要求是方法名必须相同,并且参数列表也要相同;这和重载没关系,重载是在同一个类,这是不同的类额;这个时候我们在前面加上一个注解@override来提示我们注意 重写的要求,方法名和参数列表都要相同,不相同就会报错
- 重写的时候访问权限是不能降低的,可以不变和升高,如果是public,那只能是public了
- 重写方法时返回值类型必须相同或是其子类
- 如果父类的方法和属性不想被子类继承,那么我们就在父类的属性或方法前加一个权限private
final 关键字(常量定义标准格式)
- 如果父类的属性和方法允许被子类继承但是不允许被重写,这时就要用到final关键字,这个关键字我们之前说过,在说JAVA SE 基础时中的变量时说过,那就是我们不想变量的值修改,那么就加一个final变成常量,类似于C语言里的const
- final意思是最终,那么就是不允许重写的,final的位置和static都是在访问权限之后
public final float getX//这样之后我们的SpecialPoint2D就不能重写该方法了
{
return x;
}
- 这里我们不仅是方法不可以使用final,普通的属性也就是成员变量也就可以加上final修饰,不允许修改,那这就变成常量了,这和我们之前说的一样,但是我们这种方式不是很正规,Java里对于常量定义是有要求的
//常量定义:public static final 数据类型 变量名(全部大写) = 值;既然是常量那就是类变量了,当然该加static 但是要求所有的都可以访问,所以加public
public static final String MOTHERCOUNTRY = "CHINA";//只要是中国人,那么这个类的祖国都是中国,MOTHERCOUNTRY就是常量,也是类变量
- 当我们的父类不行被其他任何类继承怎么办,那么我们就直接在类名前面加上关键字final
public final class Animal{
//不能被继承了,Java的类库里就有一个不能被继承的类Sting类,它就有final修饰
}
- 子类只能继承属性与普通方法,不会继承父类的构造方法,但是子类构造方法会先调用父类构造方法super();
super关键字
-
super的作用就是访问父类的构造方法,所以我们之前系统的source加载的时候就在第一行有这个语句
-
super();就是访问父类中无参的构造方法,super(200);之类就是访问有参的构造方法;
-
super还可以访问父类中的成员方法(这个就是如果我们重写了父类中的方法或者属性)但是我们就是想访问父类中的原来的方法,这是就用super
public float getFatherMethod
{
super.getX();//这样我们就访问了父类的被重写的方法了
}
//或者我
- 这个可以联想this关键字,这里this关键字是处理同一个类中成员变量相同的问题,而super就是解决继承时子类与父类变量或方法相同的情况,super和this都不能在静态环境中使用
Java的单继承
Java里不支持多重继承,只支持单继承,但是支持多层继承;这个意思时 老虎可以继承陆栖动物,而陆栖动物又继承动物类
Object类
Java里Object类是所有类的父类,所以我们在.引用的时候就会出现我们没有定义的方法
包装类
这个是什么呢,其实就是我们之前所说的包裹体
装箱与拆箱
装箱就是讲基本数据类型转换成包装类的过程,拆箱就是将 包装类转换成基本数据类型的方法
基本数据类型转字符串
一共由三种方法来实现这个操作
- 使用包装类的toSting()方法
- 使用Sting类的valueOf()方法
- 用一个空的字符串加基本类型
我常用的就是第三种,就是使用 + 来连接就好了
将字符串转换成基本数据类型
一共有两种方式来解决
- 调用包装类的parseXxx静态方法
- 调用包装类的valueOf方法
String s;
int i = Integer.parseInt(s);
int j = Integer.valueOf(s); //valueOf就是将其转成包裹体
抽象类
上转型对象
将子类的对象的引用放到父类的对象中
//像之前我们的SpecialPoint2D是Point2D的子类 extends了
//我们在Main类定义子类对象
SpecialPoint2D pointtwo = new SpecialPoint2D();//无参的构造方法
//什么是上转型
Point2D pointtwo = new SpecialPoint2D();//这样定义出来的对象是只能访问父类的属性方法的,不能访问子类特有的属性方法,这是由前面我们定义的时候就说他是父类决定的 “假装是儿子也不能改变是爸爸的事实”
抽象类abstract—关键字(面试不要出错)
被关键词abstract修饰的类,就称为抽象类
抽象方法
在类中,如果某个方法只有声明,而没有实现,这样的方法,称之为抽象方法;对于抽象方法我们就必须在访问权限之后加上关键词abstract;并且要在类前面加上abstract修饰,这样才可以编译通过
public abstract Point2D{
public abstract float getX();//没有大括号,没有实现,抽象方法
}
- 如果一个类中有抽象方法,那么它一定是抽象方法(一旦内部有抽象方法,类如果不加abstract就会报错)
- 如果一个类是抽象类,该类不一定有抽象方法(只要有abstract关键字就是抽象类了,和有没有抽象方法没关系!!)
- 抽象类的特征是不可以被实例化,也就是我们不能定义对象来引用这个类中的属性与方法,如果要实例化,那么我们就要用子类去继承该类,并重写该类中所有的抽象方法就是只有声明的方法
所谓的多态就是在继承时,出现了不同的子类,所以就叫做多态
- 抽象类怎么使用?是不是还没有发现它的用途,它的用法就是解决代码灵活性,搭配上转型对象来实现多态但相似的操作:
比如下面我来说一个需求
新的学期到了,我们迎来了新的同学,我们现在要进行破冰游戏,破冰游戏是模仿动物叫声:我是X,我这样子叫“ X";,现在你要编写驱动程序实现这个功能,请注意班上人数很多,要尽可能高效
我们这里就可以先抽象一个动物类,因为从需求中找到了动物这个名词,然后它的属性是名称加叫声;然后有不同的动物,我们现在只能修改X位置的东西;那我们就要在具体化类,比如🐕,🐖类;我们来实现一下,所以抽象类就是为了实现多态
package java_study;
public abstract class Animal {
public abstract String getName();
public abstract String getCry();
}
package java_study;
public class Dog extends Animal{
@Override
public String getName() {
return "dog";
};
@Override
public String getCry() {
return "汪汪汪";
}
}
package java_study;
public class Pig extends Animal{
@Override
public String getName() {
return "pig";
}
@Override
public String getCry() {
return "ke ke ke";
}
}
package java_study;
public class SimulateCry {
public void simulateCry(Animal what){//忘记写括号了,形参也要是具体的对象,那不可能就一个类名;类比我们double i;其实这里的i也可以看作一个对象,类只是一种数据类型
System.out.println("The"+ what.getName() + "叫声是"+what.getCry());
}
}
SimulateCry sim = new SimulateCry();
sim.simulateCry(new Dog());//这就是上转型变量的用处
sim.simulateCry(new Pig());//传递参数也就是使用具体的对象,所以这里要new Pig();
//声明用父类,但是传递参数用子类
API(application programming interface)应用程序接口
API is the messager that take requests and tell a system what you want to do. And then return the respose back to you
举个例子:API就是餐厅的服务员,你是一个顾客,在看着你的菜单,厨房作为system在准备你的订单,你和厨房之间怎么联系呢,就需要API 服务员来帮忙 将你的需求告诉系统,然后再将系统的反馈(food)交给你,所以有了API就有了万物互联的可能。
API 是一些预先定义的方法,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。
今天的精力着实有限,API我们就只先介绍这些内容,明天我将详细介绍一下API的应用~