我的Java回忆之路-基础。

本文深入浅出地介绍了Java语言的三大特性:封装、继承和多态,并探讨了它们的实际应用场景和重要性。此外,还涉及了Java的数据类型、方法的重写与重载等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说明:该文是本人回忆自己学习Java过程中产生的理解和总结,不能保证正确性和条理性。如果有不正确的地方欢迎提出,万分感谢。

 

Java的起源和历史,这些文字性的东西,我就不详细介绍了,这些基本每本这方面的书都会有。

先说说Java这个语言,源于C++但脱胎于C++,引入了很多很有意思的特性。

Java的三大特征

1.封装

说到封装,不得不提一个概念:万物皆对象。通过合理的抽象获取一类事物的共有特征,将这些特征包装成一个类。而与之相对的对象,则是表示这个类表示的事物中的某个个体。换句话就是,类表示一种,对象表示一个。

而封装就是将抽象得到的数据和功能进行再包装的过程。当然,这个再包装的过程并不是简简单单的过程。因为封装的目的是简化开发和增加安全性,所以封装需要遵循以下几个规则:

    1.对外隐藏实现细节。也就是说,方法的具体实现调用方不可知。

    2.隐藏属性内容。出于安全的考虑,对象的属性必须要经过一定权限控制。

    3.用户不能像C/C++中通过指针操作对象,即用户不能直接访问内存空间。

因为封装这种特性,Java的代码安全性从起点就比其他的面向过程要安全。

现在,详细说说封装。

1.1指针

指针在C/C++中可以说是备受推崇。因为有了指针程序员可以灵活地操纵内存,使程序更有效率。但是,指针也是C/C++中一直被人所抨击的地方。因为指针的应用极其考验程序员的功底和开发习惯。指针在一些新手和不良习惯的程序员手里成为了造成内存溢出、程序崩溃的罪魁祸首。当然,这里的新手并不是那种刚刚入门的人,而是那种学了一部分就感觉自己已经精通了的人。

而Java彻底抛弃了这个让人又爱又恨的特性。通过封装,将对象的引用传递给用户,用户通过引用操作对象。这样用户就不能操作内存了。

但是这样也有一定程度的弊端,那就是程序员无法主动干涉内存释放。虽然JVM接管了内存释放,但是当用户同时多次申请大量内存的话就会发生堆栈溢出,也就是OutOfMemoryError。我想很多人都遇到过。对于这个错误,暂时不清楚解决方法。目前我只了解一个可以一定程度上的缓解方法,那就是在定义类的时候重写finalize()方法。关于这个方法后面会介绍。

1.2类、属性、方法

前面提到类是对一类事物的抽象。所以可以了解到, 是抽象的。那么,到底抽象了哪些东西呢?抽象了事物的特性(属性),事物应该具有的功能(方法)。

属性:事物的特征、特性,或者说是概念定义。就像矩形的长、宽等这些属性,我们定义了长,然后再定义宽,就定义了一个矩形。所以,当我们定义了类的所有属性,我们就定义了一个可以区分的对象。

方法:事物具有的功能,或者与其有极大关联的功能。还是矩形这个例子,矩形的计算周长、计算面积,这些方法并不算是矩形具有的功能,但是因为这些功能的主体不明而且又与矩形关联巨大,所以,这些方法就会抽象到矩形类里面。

类、属性、方法,这些概念都是抽象而来的。那么,如何选择抽象程度呢?个人经历和一些网上的前辈给出的建议是:根据实际业务需求。比如说,人,如果抽象成类,将会具备很多属性和功能。如果,应用到身份证管理系统中的话,那么人具备的吃饭、体重这些再抽象就不合适了。(因为个人语言能力所限,例子可能不是很恰当,希望能够表达出意味来)

1.3访问权限控制

说起封装,就不得不提访问权限控制了。因为正是访问权限控制完善了封装。

Java的访问权限控制简略介绍如下:

   同一个类 同一个Java文件中其他类   同一个包 子类 其他类 备注
 private  支持 不支持  不支持  不支持  不支持 接口不支持private。内部类可以访问其外部类的private属性、方法
 protected  支持 支持  支持  支持  不支持 
 default  支持 支持  支持  不支持  不支持  default作为访问权限关键字时,可以写,也可以不写。
 public  支持 支持  支持 支持  支持  public 控制的方法和属性是对全局公开的。

当然,上表仅仅是一种简略介绍。

private:如果我们使用private控制时,就表示我们不想要其他其他用户访问它,它是对类内部公开。

default:也称为包内公开,也就是说default控制的方法、属性这些是对包公开。

protected:如果我们希望将某个方法交给子类去实现的话,那么就要用protected作为访问权限控制。

public:全局公开,这个是对全局公开的。也就是说,只要在你知道有这个类,那么就可以访问。

2.继承

根据《Java编程思想》中对继承的说明,继承就是“A is B”。我认为,这个很好的说明了继承的特性。只有满足“A is B”,才能说A继承了B。

与C++中不同的地方,Java只支持单继承。换句话就是一个父类有多个子类,而一个子类只有一个父类。那么,如果我们需要像C++中“继承多个类”呢?这就交给了接口。

这里插一句,继承是具有传递性的,也就是说“A is B,C is A”那么“C is B”。

Java中继承的关键字是:extends。

例子代码如下:

public class B{
	private int ival;
	private String test;
	
	protected void setIval(int ival){
        this.ival = ival;
	}
	
	private void init(){
		ival = 10;
		test = "Hello World!"
	}
	
	public void test(){
		System.out.println("test : "+test);
	}
}
public class A extends B{
	
}

 

那么,A类可以访问它父类B的哪些内容呢?

protected void setIval(int ival);
public void test();

有且仅有这些A类可以访问。似乎有些少啊。虽然看上去是这样的,但其实A类可以拥有自己的属性和方法,同时A类可以重写父类中它可以访问的方法,甚至可以修改protected控制的方法访问权限,当然了不能降低其访问控制范围,换句话说,就是可以将其公开。

同时,在实际应用中,子类甚至可以代替父类对象。

这里提到了重写,所谓的重写呢,个人理解就是子类写了一个和父类具有相同参数列表、相同方法名、相同返回类型、相同或大于父类访问控制权限的方法。这里有一个前提,就是子类要重写的这个方法不能是private的。至于default,我只能说这个是对包公开的。也就是在一个包里的子类可以重写,和父类不在一个包的子类则不能重写。

3.多态

多态分为运行时多态和编译时多态。运行时多态是动态多态,其具体引用的对象在运行时才能确定。编译时多态是静态多态,在编译时就可以确定对象使用的形式。这里介绍不是很详细,具体可以参照http://blog.youkuaiyun.com/tophot115/article/details/3016033

个人认为多态就是对重写、重载以及继承、实现的综合应用。

以上简略的介绍了Java的三大特性。由于个人水平所限,无法表述其亮点的百中之一。在这里,我推荐一本《Java编程思想(Thinking in Java)》。其高明之处,我就不用自己浅薄的语言描述了。



数据类型

Java的数据类型大体分为基本数据类型和引用数据类型。

1.基本数据类型

1.1 数字型

字节型:byte(Byte) 其取值范围是:-128~127,数据宽度:8位

短整型:short(Short)其取值范围是:-32768~32767 数据宽度是:16位

整型:int(Integer)其取值范围是:-2147483648~2147483648 数据宽度是:32位

长整型:long(Long)其取值范围是:-9223372036854775808~9223372036854775807  数据宽度是:64位

浮点型:float(FLoat) 其取值范围是:1.4E-45~3.4028235E38

双精度:double(Double) 其取值范围是:4.9E-324~1.7976931348623157E308

关于浮点型和双精度,具体的长度我不太了解了。

现在,具体说一下这几个数字型的数据类型。括号里面的是对应的Java封装类,里面有一些比较使用的方法。这里就不具体的一一阐述。这里说一下大概的应用规则:

1.byte 因为其比较窄的存储范围,如果用来做多次数学算术的话,很容易发生溢出,造成数据丢失的现象。所以,平时一般用来作为对象的状态表示。当然也可以做为小数值的计算,不过不推荐。

2.short 大型项目中在实际中很少使用到,可能嵌入式中会用到。

3.int 可以说是最常用的整数类型。

4.long 用来表示比较大的整数类型。在声明的时候,建议在值后面加上‘L’或‘l’(小写的L)。这样有益于增强代码的阅读性。(印象中,如果不加L编译器会报错,但MyEclipse对此没有任何反应)。

5.float和double,都用来表示小数,如果不特殊注明,Java默认该小数是double类型的。

1.2非数字型

布尔型: boolean(Boolean) 取值true,false

字符型:char(Character)表示一个字符,这个字符可以是类似中文的宽字符,也可以是类似英文数字的短字符。

 

与C++不同的是,Java的布尔型关键字采用的是:boolean,而不是bool。同时,还有一个区别就是,boolean类型的变量不能直接转换为数字型变量。而C++的bool型,可以完成bool和int之间的转换。

Java在现有流行的JDK版本中,char类型都采用了UNICODE编码,也就是说,现有语言的单个字符都能用char类型来表示(没有试验过,这是UNICODE的定义的,Java的char采用了UNICODE编码,我想应该也可以吧)。

2.引用数据类型

字符串型:String

日期型:Date

大整数:BigInteger

大精度小数:BigDecimal

其他类型:Class类

引用数据类型,说白了也就是我们在编写的时候所写的Java类。这就是我们常说的引用数据类型。

 

方法的重写、重载

1.重写(Override)

重写,一般指子类重写父类中子类可以访问的方法。

重写需要满足的条件是:

相同的方法名,相同的返回类型,相同的参数列表,相同或者更加宽的访问权限控制。

为什么需要重写呢?

我想我们平时肯定会遇到这么一个问题,有这么一个方法,父类和子类有着不同的实现。就比如说吃饭这个动作,父亲习惯拿筷子,而他的小儿子却喜欢用勺子。那么,如果没有重写的话,我们应该怎样表示呢?难道说像这样定义?

class Father{
	public void fatherEat(){
		System.out.println("我是父亲,我习惯用筷子");
	}
}
class Son{
	public void sonEat(){
		System.out.println("我是儿子,我喜欢用勺子");
	}
}

如果你喜欢这样,那么当类多了之后,继承关系复杂之后,你会发现你的方法名字可能会很长,而且不具备良好的阅读性。

那么使用了重写之后,又会是怎样的?

class Father{
	public void eat(){
		System.out.println("我是父亲,我习惯用筷子");
	}
}
class Son{
	public void eat(){
		System.out.println("我是儿子,我喜欢用勺子");
	}
}

那么,这样你就会很轻易的发现,无论父类有多少个子类,有多少个子类的子类,方法只有一个。

既然有了重写,我们在实际中应该怎样应用呢?

我们先来看看这两行代码的结果是怎样的:

Father son = new Son();
son.eat();

如果知道结果是输出

我是儿子,我喜欢用勺子

那么,你基本明白了重写是怎样用了。

因为继承的关系,我们在实际开发应用中,子类对象可以作为父类对象使用。但是,当子类对象作为父类对象使用的时候,就会产生一个问题,那就是这个子类对象只能调用父类所拥有的方法。那么,这个方法的具体实现是使用父类的呢,还是子类的呢?

这时候,如果子类重写了这个方法,将会调用子类对象自己重写的方法,如果没有则调用父类原有的。

这样就会实现了运行时多态这一特性。

重写也是对程序代码扩展性的一种支持。

2.重载(Overload)

重载的官方定义我不太清楚了。但是重载的实现需要满足一下条件:

相同的访问控制权限(一般都是public,因为需要被调用)、相同的方法名、不同的参数列表。

Java是通过参数列表的不同来区别方法的不同。

重载实现了编译时多态。

转载于:https://my.oschina.net/c7jie/blog/226021

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值