序言:主要记录一下java的学习笔记,用作面试复习,参考的学习资料是尚硅谷Java网课链接
面向对象是P39~P69内容
文章目录
一、类和对象
概念不赘述,这里记录一些术语和例子:
-
对象将内存地址赋值给了变量,所以变量引用了内存中的对象,所以称之为引用变量,而该变量的类型称之为引用数据类型。
-
此外还有空对象,所有引用类型变量的默认取值就是null
-
属性:类的对象的相同特征
二、传值方式
Java只有值传递。
首先明白:Java内存主要由三部分组成:
- 堆
(1) 存放new的对象和数组
(2) 可以被所有线程共享,不会存放别的对象引用
(3) 引用数据对象是放在堆中的 - 栈
(1) 存放基本数据类型
(2) 引用对象的变量 - 方法区
(1) 可以被所有线程共享
(2) 包含了所有的class和static变量
Java中每个方法进入运行时,JVM都会创建一个栈帧,然后将栈帧压入栈中,如果方法中还嵌套有方法就继续创建栈帧,执行完后弹出栈帧即可。
比如有main方法和test方法,有以下代码:
public static void main(String[] args) {
int i = 10;
test(i);
System.out.println(i);
}
public static void test(int i){
i = i+10;
}
打印出来的结果是i = 10,
栈帧不同,内存区域不同,运行完test方法后,弹出栈帧,但是i的值不会改变,接着进行输出,则输出10
第二个例子:
public static void main(String[] args) {
String s = "abc";
test(s);
System.out.println(s);
}
public static void test(String s){
s = s+10;
}
打印出s的结果仍然是abc,(个人理解)这里在运行test方法时,s是指向的abc的一个副本abc,然后s = s+10使得该副本变成了abc10,也就是上图紫色圆圈所示。
s = s+10
拓展:此处+号的进行字符串拼接的原理是StringBuilder.append()方法;
s = (new StringBuilder().append(s).append("10").toString());
第三个例子:
public static void main(String[] args) {
User user = new User();//引用数据类型是放于堆中的
user.name = "张三";
test(user);
System.out.println(user.name);
}
public static void test(User user){
user.name = "李四";
}
三、静态与静态代码块
把和对象无关,只和类相关的概念称之为静态
把和类相关的属性称之为静态属性
把和类相关的方法称之为静态方法
静态语法就是在属性和方法前增加static关键字
package com.example.Test;
public class Test04 {
public static void main(String[] args) {
Test t = new Test();
//成员方法可以访问静态属性和静态方法
//但是静态方法不可以访问静态属性和静态方法
t.test();
t.test1();
Test.test1();
}
}
class Test{
String name;
static String sex;
void test() {
//成员方法可以调用静态方法
test1();
System.out.println("test...");
}
static void test1() {
System.out.println("test1...");
}
}
静态代码块:
可以用来完成静态属性的初始化功能。
类的信息被加载完成后,会自动加载静态代码块,不管是new对象还是调用类中的方法。
但代码块只有在对象创建时才会被调用。
四、包
主要功能:对类进行分类管理
基本语法:
package 包完整路径
如:
package chapter01;
package chapter01.childpackage;
一个类可以没有包,但是最多一个。包名一般小写,小写方便区分包和类。
java存在不同包的相同名称的类,可以使用包进行区分
如 java.util.Date()
java.lang包是自动import好的,但java.util.Date之类的包就需要手动import.
若import的包里有相同名称的类,那么在使用类时仍然需要增加包名。
五、构造方法
构造方法:专门用于构建对象,类在创建时JVM会自动添加一个无参构造方法。
但是当手写了有参构造方法时,无参构造方法也必须显式的定义出来。有参构造方法一般是用于对象属性的赋值。
//在new对象时,就会调用构造方法
User user = new User();
当类中含有代码块和构造方法时,会先执行代码块,再执行构造方法的内容。
六、继承与构造方法
继承可以减少代码编写,提高效率
-
类存在父子关系:子类可以直接获取到父类的成员属性和成员方法。
-
类的继承只能是单继承,一个类只能有一个父类,但一个父类可以有多个子类。
-
注:接口可以是多继承的
-
如果父类和子类含有相同的属性,那么可以采用特殊的关键字进行区分(super和this)
package com.example.Test; public class Test05 { public static void main(String[] args) { Child cld = new Child(); System.out.println(cld.name); cld.test(); } } class Parent{ String name = "ZhangSan"; } class Child extends Parent{ String name = "LiSi"; void test() { System.out.println(super.name); System.out.println(this.name); } }
-
父类对象在子类对象创建前创建出来,创建子类对象前,会先调用父类的构造方法。
public class Test05 { public static void main(String[] args) { Child cld1 = new Child(); Child cld2 = new Child(); Child cld3 = new Child(); } } class Parent{ Parent(){ System.out.println("Parent"); } } class Child extends Parent{ Child(){ System.out.println("Child"); } }
-
当子类对象构造时我们知道会先调用父类的构造方法,默认情况下,使用的是super的方式,JVM会自动完成无参的super形式。即
class Child extends Parent{ Child(){ super();//这里可以省略不写,因为JVM默认写好了 System.out.println("Child"); } }
但是当父类有参时,我们就需要手动写含参数的super方法了,因为JVM只提供了无参的super方法
例:public class Test05 { public static void main(String[] args) { Child cld1 = new Child(); Child cld2 = new Child(); Child cld3 = new Child(); } } class Parent{ String username; Parent(String name){ username = name; System.out.println("Parent"); } } class Child extends Parent{ Child(){ super("zhangsan"); System.out.println("Child"); } }
七、多态
多态是一个对象在不同场景下表现出来的不同状态和形态
package com.example.Test;
public class MultiStatus {
public static void main(String[] args) {
Person person = new Person();
Person boy = new Boy();
Person girl = new Girl();
person.PersonTest();
//子类可以调用父类的成员属性和成员方法
//boy.PersonTest();
//girl.PersonTest();
//多态语法对对象的使用场景进行了约束
//这里也可以理解为Person对象没有子类的功能
boy.BoyTest();//编译器报错
girl.GirlTest();//编译器报错
}
}
class Person{
void PersonTest() {
System.out.println("PersonTest...");
}
}
class Boy extends Person{
void BoyTest() {
System.out.println("BoyTest");
}
}
class Girl extends Person{
void GirlTest() {
System.out.println("GirlTest");
}
}
八、方法的重载与重写
8.1 重载
方法重载:方法名相同,参数列表(个数,顺序,类型)不相同
注:构造方法也存在重载
实例:
在无法匹配参数时,基本数据类型可以通过提高精度来适配。
但是注意char类型不能与数值类型适配
而对于自定义的类无法匹配方法参数时,当前类会向它的父类去寻找适配参数,实例:
可以适配时:
不适配时:
B由于继承了A类,故B的父类是A,如果方法参数不是A,那么会去Object类寻找
B->A->Object
8.2 重写
九、访问权限、外部类、内部类、final
访问权限有四种。
注:公共类只能有一个,且必须与源码文件名相同(即public class 只能有一个)
- private
私有的,同一个类中可以使用 - default
当不指定访问权限时,JVM会自动分配一个默认权限,它是包(路径权限),即在同一个包下可以使用,但是注意在包的子包中的类是不能使用的(因为子包路径不同) - protected
受保护权限,在当前类和它的子类中可以使用 - public
公共的,任意使用。
外部类:在源码中直接声明的类,不能用private,protected修饰
内部类:在类中声明的类,可以看成外部类的属性
final: Java提供的语法,在数据初始化以后不能被修改,可以修饰变量和属性。被final修饰的变量也称为常量。
final也可以修饰方法,但是该方法就不能被子类重写。
final也可以修饰类,但是该类没有子类了。
final不可以修饰构造方法。
final可以修饰方法参数
十、单例模式
保证只有一个实例化对象,即可以避免因为重复new对象造成的资源浪费。
public class SimpleExample {
public static void main(String[] args) {
User1 user1 = User1.getInstance();//类.静态方法
User1 user2 = User1.getInstance();//类.静态方法
System.out.println(user1.hashCode());
System.out.println(user2.hashCode());
}
}
class User1{
//静态方法不能调用成员变量和成员方法,但反之可以
//静态方法可以调用静态变量
//单例模式:
/* 1.构造方法用private修饰,避免直接被主方法调用
* 2.新建静态方法getInstance(),判断是否已经存在实例化好的对象,
* 对象存在就直接返回,否则new一个
*/
private static User1 user = null;
private User1() {
}
public static User1 getInstance() {
if(user==null) {
user = new User1();
}
return user;
}
}
hashcode值相同,则获取的两个对象是同一个对象
十一、抽象类和抽象方法
显然final不能修饰抽象类和抽象方法
用abstract修饰抽象类和抽象方法
抽象方法:只有声明,没有实现的方法
abstract class Person{
public abstract void eat();
}
抽象类无法直接实例化,但是可以通过子类间接实例化抽象类对象:子类继承抽象类,在实例化子类对象时,抽象类对象会被先实例化出来。
如果抽象类中含有抽象方法,那么子类继承抽象类需要重写抽象方法,将方法补充完整。
抽象类中可能有非抽象方法
public class Test07 {
public static void main(String[] args) {
Chinese c = new Chinese();
c.eat();
}
}
abstract class Person{
public abstract void eat();
Person() {
System.out.println("Everyone was created equal.");
}
}
class Chinese extends Person{
public void eat() {
/*父类是抽象类,且具有抽象方法eat()
* 故需要对抽象方法eat()进行重写
*/
System.out.println("Chinese use chopsticks to eat.");
}
}
十二、接口、匿名类
12.1 接口
接口:可以理解为规则,所有类的对象都应该遵循接口,类可以实现接口
基本语法:interface 接口名称
接口是抽象的,属性和行为的访问权限必须是公共的
属性应该是静态的,跟类相关,跟对象无关
接口可以被类实现,通过implements关键字,
个人理解:接口中定义约束规则(即方法),类中具体实现接口中的方法
package com.example.Test;
public class Interface01 {
public static void main(String[] args) {
Computer c = new Computer();
Light light1 = new Light();
c.usb1 = light1;
Light light2 = new Light();
c.usb2 = light2;
c.powerSupply();
}
}
interface USBInterface{
}
interface USBSupply extends USBInterface{
public void powerSupply();
}
interface USBReceive extends USBInterface{
public void powerReceive();
}
class Computer implements USBSupply{
public USBReceive usb1;
public USBReceive usb2;
public void powerSupply(){
System.out.println("电脑提供能源");
usb1.powerReceive();
usb2.powerReceive();
}
}
class Light implements USBReceive{
public void powerReceive() {
System.out.println("电灯接受能源");
}
}
12.2 匿名类
即没有名称的类
public class Test08 {
public static void main(String[] args) {
Me me = new Me();
//匿名类
me.sayHello(new Person1() {
public String name() {
//重写抽象方法
return "wangwu";
}
});
}
}
abstract class Person1{
public abstract String name();
}
class Me{
public void sayHello(Person1 person) {
System.out.println("你好"+person.name());
}
}