当我们希望一个类不能够被实例化时,可以将这个类定义为抽象类
语法:
abstract class T{}
T t = new T(); //编译错误
抽象类的特点:
不能够被实例化
可以有抽象方法
abstract class T{
abstract void t();//抽象方法
}
抽象方法不带有方法体,用分号结束
抽象类和抽象方法
用abstract关键字修饰不能在类内实现的方法,这样的方法称为抽象方法,含有抽象方法的类必须声明为abstract,这样的类叫抽象类。
抽象类中不一定包含抽象方法,但包含抽象方法的类一定要声明为抽象类
抽象方法本身不具备实际的功能,只能够用于派生时重写(即在子类中重写)。
如果一个类被定义为抽象类,则该类不能进行实例化,必须通过重写的方式来实现抽象类中的方法。
【举例】
package test;
//定义一个类House(房子)
public class House {
private Z z;
public void setZ(Z z){
this.z=z;
}
public void start(){
z.zhuan();
}
}
package test;
//定义一个抽象类Z(砖块)
public abstract class Z {
public abstract void zhuan();//抽象方法
public void tt(){
system.out.println("tt.....");
}
}
package test;
//定义一个Tu类(凸砖块)
public class Tu extends Z {
//重写抽象类中的抽象方法
public void zhuan(){
System.out.println("Tu.....");
}
}
package test;
//定义一个fang类(方砖块)
public class fang extends Z{
//重写抽象类中的抽象方法(重写只要定义方法相同就行)
public void zhuan(){
System.out.println("fang.....");
}
}
package test;
//定义一个测试类
public class TestHouse {
public static void main(String[] args){
House house=new House();
house.setZ(new Tu());
house.start();
house.setZ(new fang());
house.start();
//Z a=new Z();//抽象类不能被实例化
Z a=new Tu();
a.zhuan();
}
}
【运行结果】
Tu…..
fang…..
Tu…..
当我们想强调一个功能,而不是类型时,可以通过定义接口的方式来实现
interface 插座{
void 通电();
}
这里定义了一个插座,目的在于通电,关注的是通电这个功能,而不关注哪种类型的物质插上去
接口的实现
class 人 implements 插座{
public void 通电(){
System.out.println(“呜呼哀哉”);
}
}
实现了接口之后,也就相当于具备了接口定义的功能,当然必须实现接口中定义的方法
这里我们给出另一个实现类:
class 手机 implements 插座{
public void 通电(){
System.out.println(“充电中”);
}
}
当一个类实现了某个接口后,我们可以将这个类的实例定义为这种接口类型
如上面的例子中,我们可以这样定义:
插座 n1 = new 人();
插座 n2 = new 手机();
接口中的属性:
interface T{
int a = 0;
}
实际上T中定义的a的实际定义方式为:
public static final int a = 0;
以上public, static, final为缺省加上的,且不能改变,在后面的课程中一一讲解
【举例】
package test1;
//定义一个注册接口
public interface Register {
public void yanzheng();//验证功能
}
package test1;
//定义一个登录接口
public interface Login {
public void fukuan();//付款功能
public void chuanshu();//传输功能
}
package test1;
//定义一个User类来实现这些接口
public class User implements Login,Register {
private Login user;
public Login getUser() {
return user;
}
public void setUser(Login user) {
this.user = user;
play();//调用play()方法
}
//方法的重写
public void fukuan() {
System.out.println("请付款");
}
public void chuanshu() {
System.out.println("请传输数据");
}
public void yanzheng() {
System.out.println("验证信息");
}
public void play(){
System.out.println("我被接口类型对象调用");
}
}
package test1;
//定义Main类来运行
public class Main {
public static void main(String[] args){
Login t=new User();//接口Login不能实例化
t.fukuan();
t.chuanshu();
t.yanzheng();//错误,Login中未定义该方法
Register b=new User();
b.yanzheng();
User c=new User();
c.setUser(t);
}
}
运行结果:
请付款
请传输数据
验证信息
我被接口类型对象调用
static修饰的方法叫静态方法
public static void main(String args[]){}
static修饰的数据叫静态数据
static int a;
目的
使该方法或数据独立于类的实例对象,只能使用类去访问,而不是类的实例对象,所以也叫全局方法和数据
【举例】
class A{
static int count=0;
int m=0;
A(){
count++;
m++;
}
static void print(int srt){
System.out.println(str);
}
}
class Test{
public static void main(String[] s){
A a1=new A();
A a2=new A();
A.print(a1.m);//1
A.print(a2.m);//1
A.print(a1.count);//2
A.print(a2.count);//3
A.print(A.count);//3
}
}
【答】因为Java如果要创建一个对象,就必须要使用构造方法,否则对象无法创建。那么为什么前面我们没用到构造方法,也创建了对象呢?这是因为如果你没有自定义构造方法,Java就会给每一个类提供一个默认不带参数的构造方法;而一旦你自己定义了构造方法,则默认的构造方法会被覆盖,无法再继续使用。
构造方法还有一个用途就是传参数,如果之前声明了参数,那么在实例化对象的时候,可以将参数传过来,即:
类名 对象名 = new 构造方法(参数);
final 修饰类 不能被继承
如String, Integer, Boolean…
如:
final class A{}
class B extends A{} //编译错误
final 修饰变量 不能被修改
final int a = 0;
a = 10; //error
final Student stu = new Student();
stu.name = “abc”;// 正确,因为是stu被final,而不是stu存放在堆中的属性name被final
stu = null;// 错误
final Student[] stus = new Student[2];
stus[0] = new Student() ;// 正确,因为是数组stus[]被final,数组是复杂类型,栈中存地址,堆中放数据,此处堆中存的是对象类,也是复杂类型,其中栈中存地址,堆中放属性。
stus[0].name = “abc”; // 正确
final 修饰成员方法 不能被重写
class A{
final void test(){}
}
class B extends A{
void test(){} //编译错误, 方法不能重写
}