(这一节内容有很多琐碎的知识点)
1、概念说明
• 定义类(类的组成)
• 属性 field
• 方法 method
• 构造方法 construtor
• 其他:代码块 静态代码块 内部类
• 创建对象
• 类名 对象名 = new 类名();
• Person p1=new Person();
• 调用类的属性和方法
• 对象名.成员变量
• 对象名.成员方法
类的属性
• 属性 field,或者叫成员变量• 属性用于定义该类或该类对象包含的数据或者说静态属性。
• 属性作用范围是整个类体
• 属性定义格式:
2、先用一个程序看看其内存是怎么放置的
引用一篇文章:https://www.cnblogs.com/huangminwen/p/5928315.html
jvm的问题等到后面的文章更新
3、局部变量和成员变量区别
1、声明位置:成员变量在不同类中,局部变量在方法中 (局部变量是运行时在栈中即时创建的,而成员变量是)
2、 作用范围不同: 一个当前类的方法 ,一个当前方法
3、不同的方法中即使有同名的局部变量,没有关系,互不影响,建议相同
4、成员变量有默认值;局部变量没有默认值(所以对于局部变量要先赋值,不然编译出错)
5、内存存放的位置的:栈内存中 堆内存中
对于内存存放位置再做一定的说明(相关jvm知识)
对于局部变量,如果是基本类型,会把值直接存储在栈;如果是引用类型,比如String s = new String("william");会把其对象存储在堆,而把这个对象的引用(指针)存储在栈。 例如 String s1 = new String(“william”); String s2 = s1; s1和s2同为这个字符串对象的实例,但是对象只有一个,存储在堆,而这两个引用存储在栈中。 类的成员变量在不同对象中各不相同,都有自己的存储空间(成员变量在堆中的对象中),基本类型和引用类型的成员变量都在这个对象的空间中,作为一个整体存储在堆。而类的方法却是该类的所有对象共享的,只有一套,对象使用方法的时候方法才被压入栈,方法不使用则不占用内存。栈: 存放:局部变量 ,先进后出,自下而上存储 ,方法执行完毕,自动释放空间
堆: 存放new出来的对象 ,需要垃圾回收器来回收 (gc)
方法区: 存放:类的信息(代码)、 static变量、字符串常量等.
4、构造方法(构造器)
构造器是一种特殊的方法:
• 构造器的方法名必须和类名一致!
• 构造器虽然有返回值,但是不能定义返回类型(返回值的类型肯定是本类),不能在构造器里调用 return。
• 通过new关键字调用!!
• 如果我们没有定义构造器,则系统会自动定义一个无参的构造方法。如果已定义则编译器不会 添加无参数构造方法!
• 与普通方法一样,构造方法也可以重载、
5、方法调用
• 形参和实参• 定义方法的参数是形式参数
• 调用方法的参数是实在参数
• 调用方法时要求参数个数相同,类型兼容
• 参数传递• 基本数据类型的参数传递
• 无法通过方法调用改变变量的值
• 引用数据类型的参数传递
• 可以通过方法调用改变变量的值
这里抛个问题:java是值传递还是引用传递
6、this、static关键字
this关键字
• this的作用:• this表示的是当前对象本身,
• 更准确地说,this代表当前对象的一个引用。
• 普通方法中使用this。
• 区分类成员属性和方法的形参.
• 调用当前对象的其他方法(可以省略)
• 位置:任意 • 构造方法中使用this。
• 使用this来调用其它构造方法
• 位置:必须是第一条语句
• this不能用于static方法。(讲完static,大家就知道为什么了!)
static 关键字
• 在类中,用static声明的成员变量为静态成员变量 ,或者叫做: 类属性,类变量.• 它为该类的公用变量,属于类,被该类的所有实例共享,在类被载入时被显式初始化,
• 对于该类的所有对象来说,static成员变量只有一份。被该类的所有对象共享!!
• 可以使用”对象.类属性”来调用。不过,一般都是用“类名.类属性”
• static变量置于方法区中!
• 用static声明的方法为静态方法• 不需要对象,就可以调用(类名.方法名)
• 在调用该方法时,不会将对象的引用传递给它,所以在static方法中不可访问非static的成员。
• 静态方法不能以任何方式引用this和super关键字
(静态代码块和静态变量是最先加载的资源,静态资源是公共资源,公共资源是不能调用私有资源的(但可调用公共资源),即静态代码块里不能调用非static的变量等(私有资源可调用公有的))
7、jdk主要的包
• java.lang
• 包含一些Java语言的核心类,如String、Math、Integer、System和Thread,提供常用功能。
• java.awt
• 包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用 程序的图形用户界面(GUI)。
• java.net
• 包含执行与网络相关的操作的类。
• java.io
• 包含能提供多种输入/输出功能的类。
• java.util
• 包含一些实用工具类,如定义系统特性、使用与日期日历相关的函数。
注意要点:
• java会默认导入java.lang包下所有的类,因此这些类我们可以直接使用。
• 如果导入两个同名的类,只能用包名+类名来显示调用相关类: java.util.Date date = new java.util.Date();
8、面相对象的三大特性
• 继承 inheritance
• 子类 父类
• 子类可以从父类继承属性和方法
• 子类可以提供自己单独的属性和方法
• 封装/隐藏encapsulation
• 对外隐藏某些属性和方法
• 对外公开某些属性和方法
• 高内聚 :就是类的内部数据操作细节自己完成,不允许外部干涉;
• 低耦合 :仅暴露少量的方法给外部使用。
• 多态 polymorphism
• 为了适应需求的多种变化,使代码变得更加通用!
• 面向过程只有封装性(功能的封装,而没有数据的封装),没有继承和多态
9、访问控制符
成员的访问权限四种都有,类的访问权限只有public和default(不写默认是default)
一般成员变量写private,封装的工具方法写private,希望被调用的写public
10、继承
1、继承:如果定义一个类时,没有调用extends,则它的父类是:java.lang.Object
1)、Object类是所有Java类的根基类 ,如果在类的声明中未使用extends关键字指明其基类,则默认基类为Object类
(Object类toString方法: •默认返回:包名+类名+@+哈希码 ,可以重写!像String、Array等内部就进行了重写 )
2)说到继承就会想到重写/覆写 :
• 在子类中可以根据需要对从基类中继承来的方法进行重写。
• 重写方法必须和被重写方法具有相同方法名称、参数列表和返回类型。
• 重写方法不能使用比被重写方法更严格的访问权限。(由于多态)
3)super关键字
• super是直接父类对象的引用。 • 可以通过super来访问父类中被子类覆盖的方法或属性
4)、父类方法的重写:
• “==”:方法名、形参列表相同。
• “≤≤”:返回值类型和异常类型,子类小于等于父类。
• “≥”:访问权限,子类大于等于父类
5)、equals和==
• ==:
• 比较两基本类型变量的值是否相等
• 比较两个引用类型的值即内存地址是否相等,即是否指向同一对象。
• equals() :
• 两对象的内容是否一致 (自定义的类要重写equals()和hashcode())
• 示例
• object1.equals(object2) 如:p1.equals(p2)
• 比较所指对象的内容是否一样
• 是比较两个对象,而非两个基本数据类型的变量
• object1 == object2 如:p1==p2
• 比较p1和p2的值即内存地址是否相等,即是否是指向同一对象。
• 自定义类须重写equals()和hashcode(),否则其对象比较结果总是false。
问题:子类继承了父类的哪些东西?调用方法时是调用重写的还是父类的,构造方法调用顺序?父类和子类各类代码方法的执行顺序?子类的this和super?子类和父类的转型?为什么要重写equals()和hashcode()?equals()和hashcode()有什么联系?
java的类都重写equals()和hashcode()了吗? 这些问题在下一篇文章解析
11、多态
• 多态性是OOP中的一个重要特性,主要是用来实现动态联编的,换句话说,就是程序的最终状态只有 在执行过程中才被决定而非在编译期间就决定了。这对于大型系统来说能提高系统的灵活性和扩展
性。• java中如何实现多态?使用多态的好处?
• 引用变量的两种类型:
• 编译时类型(模糊一点,一般是一个父类)
• 由声明时的类型决定。
• 运行时类型(运行时,具体是哪个子类就是哪个子类)
• 由实际对应的对象类型决定。
• 多态的存在要有3个必要条件:
• 要有继承,要有方法重写,父类引用指向子类对象
例:List list = new ArrayList(); 当编译时引用变量是List类型,当运行时引用变量是ArrayList类型(编译看左边,运行看右边)
上面的例子就是一种引用数据类型的类型转换 (即子类和父类的转型)
• 子类转换为父类:自动转换 (向上转型)• 上转型对象不能操作子类新增的成员变量和方法。
• 上转型对象可以操作子类继承或重写的成员变量和方法
• 如果子类重写了父类的某个方法,上转型对象调用该方法时,是调用的重写方法。
• 父类转换为子类:强制转换 (这种转换可能出现错误)??
12、final关键字
• final可以用来修饰变量,方法,类。
• 修饰变量:变量一旦被初始化便不可改变,相当定义了一常量。
• final int x=3;
• x=4;
• 修饰方法:final方法是在子类中不能被覆盖的方法
• final returnType methodName(paramList){...}
• final void eat() { … }
• 修饰类:final类是无法被任何类继承的。
• final class finalClassName{ ... }
• final class Person{ … }
final不能和哪些关键字一起用?java中哪一些类/属性/方法用了final?(例String)
13、抽象类abstract、接口interface
1、抽象类要点:
• 抽象方法和抽象类均必须用abstract来修饰。
• 抽象方法没有方法体,只需要声明不需实现。
• 抽象类可以没有抽象方法,有抽象方法的一定是抽象类
• 抽象类可以包含属性、方法、构造方法。• 抽象类不能实例化,及不能用new来实例化抽象类,只能用来被子类调用。
• 抽象类只能用来继承。 (ex)
• 抽象方法必须被子类实现。抽象类的子类必须覆盖所有的抽象方法才能被实例化,否则还是抽 象类
上面这些要点在jdk1.8后有一定改动,下一篇文章解析
2、接口
• 如何实现接口
• 子类通过implements来实现接口中的规范
• 接口不能创建实例,但是可用于声明引用变量类型。
• 一个类实现了接口,必须实现接口中所有的方法,并且这些方法只能是public的。
• Java的类只支持单继承,接口支持多继承
• 接口相关规则
• 接口中所有方法都是抽象的。
• 即使没有显式的将接口中的成员用public标示,也是public访问类型的
• 接口中变量默认用 public static final标示,所以接口中定义的变量就是全局静态常量。
• 可以定义一个新接口,用extends去继承一个已有的接口(一个接口可继承多个接口)• 可以定义一个类,用implements去实现一个接口中所有方法。
• 可以定义一个抽象类,用implements去实现一个接口中部分方法。
接口的规则在1.8之后也有相应的改动,下一篇文章解析
3、
• C++支持多重继承,Java支持单重继承
• C++多重继承的危险性在于一个类可能继承了同一个方法的不同实现,会导致系统崩溃。
• Java中,一个类只能继承一个类,但同时可以实现多个接口,既可以实现多重继承的效 果和功能,也避免的多重继承的危险性。
• class Student extents Person implements Runner,Flyer• {…}
• 注意:extends 必须位于implements之前
jdk1.8后抽象类/其中的属性方法可以用什么修饰符修饰?里面可以有什么方法?什么方法可以在里面实现?子类实现需要实现全部方法?抽象类和接口的区别?可不可以创建实例?有没有构造函数?
14、方法/匿名/静态/成员内部类
总结:该文主要是对面向对象编程的基础知识点进行表面梳理,但比较细节的知识点没有列出,会在下一篇博客进行解析比较细节的知识点