面向对象的三个基本特征:封装、继承、多态。
面向对象是一种思想,而类即是思想的体现。
类其实就是一类事物的属性和行为封装体。而对应的类对象就是这类事物的表现形式或者一个实例。
以前的面向过程主要思想是过程式编程,即按照一系列行为顺序执行完成一件事情。
而面向对象其思想是指所有行为所属于一个对象,当外界对对象施以触碰(各种触发条件)时,以对象为整体做出相应的动作,来响应其触碰。
面向对象将属性和行为封装成一个整体,通过其行为改变其属性,极大的保护了数据。
顺便提一句一个古老而特别的语言Lisp,其思想之伟大。本人学习不够深入,在此不敢过多论述。有兴趣和余力的可自行了解和学习。但是切记,实际开发中用的人少之又少,其学习坡度之高,建议三思后入坑。
类
定义类:class{}
构造器
类默认会提供一个无参构造器,若在定义类时,定义了构造器则不提供。
构造器与类同名,无返回,在生成对象时调用(即new),一般用于初始化。
类中隐藏一个this,this代表当前对象。即当使用类属性或者是类成员函数时,可以直接用属性名或函数名,也可以this.属性。如:在有参构造器中,参数名与类属性重名,此时可用this.属性名与参数区分。
构造器调用时若存在超类(父类),则先调用父类的构造器,再调用本身的构造器。
this():可以调用类的构造器。
访问权限
private:私有,即只有在类内部访问。
public:公有,即类内外都可访问,外部访问需要用类对象访问,访问形式:类对象.属性。默认权限为public。
protected:保护,即类内部及其子类可访问。
静态域(属性)、静态方法
关键字static修饰的属性或方法叫做静态属性或方法。
静态属性或方法归属于类,与对象无关,所有对象共用。
静态属性或方法可以直接通过类去访问,而不需要生成对象,通过对象调用,但不代表不可以通过对象调用。
测试代码:
public class Test {
public static void main(String[] args)
{
System.out.println("静态属性访问:" + People.sta);
People.staTest();
People people1 = new People();
System.out.println("访问public属性," + people1.pub);
people1.sayName();
people1.sayAge();
People people2 = new People("people2");
people2.sayName();
people2.sayAge();
People people3 = new People("people3",12);
people3.sayName();
people3.sayAge();
Student student = new Student();
student.proTest();
}
}
class People{
private String name;
private int age = -1;
String pub = "public测试";
protected String pro = "protected测试";
public static String sta = "静态属性测试";
People(){
System.out.println("people构造");
}
People(String name){
this.name = name;
}
People(String name,int age){
this.name = name;
this.age = age;
}
public void sayName(){
if(name == null)
System.out.println("保密");
else
System.out.println("我的名字叫:" + name);
}
public void sayAge(){
if(age == -1)
System.out.println("保密");
else
System.out.println("我的年龄是" + age);
}
public static void staTest(){
System.out.println("静态方法测试");
}
}
class Student extends People{
Student(){
System.out.println("Student构造");
}
public void proTest(){
System.out.println(pro);
}
}
测试结果:
静态属性访问:静态属性测试
静态方法测试
people构造
访问public属性,public测试
保密
保密
我的名字叫:people2
保密
我的名字叫:people3
我的年龄是12
people构造
Student构造
protected测试
重载
其实,在上述构造器例子中已经出现了重载,一个类中出现多个构造器,即为构造器的重载。
重载规则:函数名相同,参数个数,参数类型不同,相同个数相同参数类型但位置不同,都可构成重载。
测试代码:
public class Test {
public static void main(String[] args)
{
demo();
demo(1);
demo(1,"");
demo("",1);
}
static void demo(){
System.out.println("无参数");
}
static void demo(int a){
System.out.println("参数int");
}
static void demo(int a,String b){
System.out.println("参数int String");
}
static void demo(String a,int b){
System.out.println("参数String int");
}
}
测试结果:
无参数
参数int
参数int String
参数String int
初始化代码块
在类中使用{},即为初始化代码块,在构造类对象时,会优先于构造器执行。
若存在父类,则父类也是按照这种顺序,但是子类的代码块不会优先于父类构造器。
测试代码:
public class Test {
public static void main(String[] args)
{
Parent parent = new Parent();
System.out.println("=====================");
Children children = new Children();
}
}
class Parent{
{
System.out.println("Parent代码块");
}
Parent(){
System.out.println("Parent构造");
}
}
class Children extends Parent{
{
System.out.println("Parent代码块");
}
Children(){
System.out.println("Parent构造");
}
}
测试结果:
Parent代码块
Parent构造
=====================
Parent代码块
Parent构造
Parent代码块
Parent构造
对象析构和finalize
java有垃圾回收机制,所以不支持析构器。但是可以在类中重写Object中的finalize方法,其会在清除对象前调用。
Object类中定义:protected void finalize() throws Throwable { }
包
包的命名一般用域名逆序命名,如:com.csdn
将代码放入包中,在代码文件的第一行加:package 包名;
导入包:import 包名.*
导入指定包中的类或者方法:import 包名.类名.方法名
静态导入:import static 包.*
包作用域
类权限修饰符:public、private
public修饰,当导入包后可以访问该类。若使用private修饰,则只有在包内可访问。
继承
java中类只有单继承,没有多继承。接口可以多继承。
子类可以继承父类中的除了private和构造器的所有。
在子类中若定义了与父类中相同的方法则会构成重载,覆盖父类方法。若还想调用父类方法可用super调用。
super用于子类调用父类中的构造器和方法。
构造器注意事项:
1、若在子类构造器中通过super调用父类构造器,则必须将调用代码放到构造器的第一行。
2、若父类中显示定义了构造器且不是无参,则在子类中一定要通过super调用父类中的构造器,否则编译报错。
3、若在子类中通过super调用父类中的构造器,则不会在调用子类构造器之前调用父类构造器。
测试代码:
public class Test {
public static void main(String[] args)
{
Children children = new Children();
children.test();
children.parentTets();
}
}
class Parent {
private String name;
private int age;
protected int money = 10;
String pub = "public测试";
Parent(){
System.out.println("Praent无参构造器");
}
Parent(int a){
System.out.println("Parent有参构造器");
}
public void test(){
System.out.println("Parent test");
}
}
class Children extends Parent{
Children(){
// super();
// super(1);
System.out.println("Children构造器");
}
public void test(){
System.out.println("Children test");
}
public void parentTets() {
super.test();
}
}
测试结果:
--将两个super注释的结果
Praent无参构造器
Children构造器
Children test
Parent test
--将第一个super打开,下面的System注释的结果
Praent无参构造器
Children test
Parent test
--将第一super注释,第二个打开,下面的System注释的结果
Parent有参构造器
Children test
Parent test
this和super比较:
this:1、引用隐式参数,2、调用该类的其他构造器
super:1、调用超类的方法,2、调用超类的构造器
多态
java中对象变量是多态的,子类对象可以赋值给父类对象,这种现象叫做多态。
其在运行时能自动选择调用那个方法,这种现象叫做动态绑定。
对象方法执行过程:
1、编译器先看对象的声明类型和方法。找到父类public的及自身类中的所有符合的方法;
2、然后编译器看调用方法提供的参数类型,找到与其匹配的,此过程称为重载解析。在此过程中允许类型转换。
其中,方法的名字和参数列表称为方法的签名。若子类中定义与父类签名相同的方法,则会覆盖,即重载。
java中,jvm预先为每个类创建了一个方法表,记录其所有方法的签名和实际调用的方法,便于查找。
当使用super调用方法时,则强制去父类方法表中查找。
关键字final可以阻止类被继承。
抽象类
abstract定义抽象类,一般只声明方法,不实现方法,但不代表不能包含具体的方法。abstract定义抽象方法,要想在类中定义抽象方法,其方法所属类也是抽象的。
即:抽象方法一定在抽象类中,但抽象类中不一定全是抽象方法。
一般的,抽象类中不实现方法,只声明方法,具体实现由子类实现。抽象类的子类必须全部实现父类中的所有抽象方法,除非子类也是抽象类。
测试代码:
public class Test {
public static void main(String[] args)
{
Child child = new Child();
child.test();
child.demo();
}
}
abstract class Parent {
public abstract void test();
public abstract void demo();
}
abstract class Children extends Parent{
public void test(){
System.out.println("Children test");
}
}
class Child extends Children{
public void demo(){
System.out.println("Child demo");
}
}
测试结果:
Children test
Child demo
Object类:所有类的父类
所有没有指明继承的类,都默认继承Object。
equals:比较两个对象是否相等。
hashCode:返回对象的散列码。
toString:返回表示对象值的字符串。
getName:返回类的名字。
getSuperclass:以Class对象的形式返回这个类的超类信息。
泛型数组列表ArrayList
定义:ArrayList<T> a = new ArrayList<>(); T表示类型,可以是任意类型(基本类型除外)。
常用API:
add:在尾部添加一个元素。
size:返回列表当前元素数量。
ensureCapacity:确保数组列表在重新分配空间情况下能保存指定数量的元素。
trimToSize:将数组存储容量减少至当前尺寸。
get:获取指定位置的元素。
set:设置指定位置的元素。
remove:删除指定位置元素。
对象包装器和自动装箱
java将基本类型重新封装了一下叫做对象包装器。
Integer、Long、Float、Double、Short、Byte、Character、Void、Boolean。
对象包装器类不允许继承,不允许修改包装在其中的值。
java SE5.0之后有了自动装箱。
自动将基本类型转换为包装器类型,称为自动装箱。
自动将包装器类型转换为基本类型,称为自动拆箱。
注意:装箱和拆箱是编译器认可的,和jvm无关。
参数数量可变
可变参数:类型...变量名。注意,可变参数只能放到参数列表最后。
测试代码:
public class Test {
public static void main(String[] args)
{
test(0,1,2,3,4,5,6);
}
public static void test(int...params){
for (int e:params)
System.out.println(e);
}
}
测试结果:
0
1
2
3
4
5
6