【java】学习笔记
b站:韩顺平Java
------------------------------------------------------------------------------------------
第一章 java简介
快速入门
// Hello类
public class Hello {
// main方法
public static void main(String[] args) {
System.out.println("hello world!");
}
}
在控制台输入以下命令,对.java文件(源文件)进行编译操作,生成Hello.class文件
javac Hello.java
在控制台输入以下命令,运行.class文件(字节码文件)(将.class文件装载到JVM机执行)
java Hello
ps:
1. 文件中有中文时,如何处理?
(1)在Sublime界面按Ctrl + Shift + P打开搜索框,然后输入Install Package,再输入ConvertToUTF8,回车
(2)左上角 文件 -> 设置文件编码 -> GBK
(3)保存,即可重新运行
2. 一个源文件中最多只能有一个public类。
3. 如果源文件包含一个public类,则文件名必须按该类名命名。
4. .java文件中的每一个类,编译后,都对应一个.class文件
转义字符
// 演示转义字符的使用
public class ChangeChar {
// main方法
public static void main(String[] args) {
// \t: 一个制表位,实现对齐
System.out.println("北京\t天津\t上海");
// \n: 换行符
System.out.println("a\nb\nc");
// \r: 一个回车(将光标移至这行的最前面,所以f会替换掉d)
System.out.println("de\rf");
// \\: 一个\
System.out.println("D:\\javacode");
System.out.println("D:\\\\javacode");
// \": 一个"
System.out.println("\"good\"");
// \': 一个'
System.out.println("\'good\'");
}
}
运行结果:
注释
单行注释://
多行注释:/* */
文档注释:
/**
*@author xxx
*@version 1.0
*/
随后使用命令行
javadoc -d 生成的文件存放的文件夹 -标签(如author) -标签 源文件
Java代码规范
类、方法的注释,要以javadoc的方式(文档注释)来写。
非Javadoc的注释(单行注释、多行注释),往往是给代码的维护者看的,着重告诉读者为什么这样写,如何修改,注重什么问题。
使用tab操作,实现整体往右缩进。
shift+tab整体往左缩进。
源文件使用utf-8编码。
行宽度不超过80。
Dos系统
原理:接受命令->解析命令->执行命令。
0026结束
0190开始
第七章 面向对象编程
一、类和对象
1、定义及区别
(1)类是抽象的,代表一类事物,比如人类,猫类..,它是数据类型;
(2)对象是具体的,实际的,代表一个具体事物,它是实例;
(3)类是对象的模板,对象是类的一个实例。
2、对象内存布局
3、属性(成员变量)
(1)基本介绍
① 从概念或者叫法上看:成员变量 = 属性 = field(字段)
② 属性是类的一个组成部分,一般是基本数据类型,也可以是引用类型(对象、数组等),定义语法同变量;
③ 属性如果不赋值,有默认值(0、null、false等)。
(2)访问属性
对象名.属性名: cat1.age
4、对象
(1)创建对象
① 先声明再创建
Cat cat;
cat = new Cat();
② 直接创建
Cat cat = new Cat();
(2)对象分配机制
(3)Java创建对象的流程简单分析
① 先在方法区中加载Person类信息(属性和方法信息,只会加载一次,之后用该类创建对象就不用加载了);
② 在堆中分配空间,进行默认初始化;
③ 把地址赋给p(p就指向对象);
④ 进行指定初始化,比如 p.name = "jack" p.age = 10。
5、成员方法
(1)方法的定义
访问修饰符 返回数据类型 方法名(形参列表..){ //方法体
语句;
return 返回值;
}
① 形参列表
② 返回数据类型:表示成员方法输出,void表示没有返回值;
③ 方法主体:表示为了实现某一功能代码块;
④ 访问修饰符:作用是控制方法使用的范围
⑤ return语句不是必须的。
(2)方法调用机制
分析的代码:
main:
第五步:getSum方法返回后,独立空间被释放
(3)方法的使用细节
① 访问修饰符
作用是控制方法使用的范围,有四种:public,protected,private, 默认。如果不写就是默认访问修饰符。
② 返回数据类型
a. 一个方法最多有一个返回值。如果返回多个结果,就要用到数组;
b. 返回类型可以为任意类型,包含基本类型或引用类型(数组,对象);
c. 如果方法要求返回数据,则方法体中最后的执行语句必须为 return 值;而且要求返回值类型必须和return的值类型一致或兼容
d. 如果方法是void,则方法体中可以没有return语句,或者只写return。
③ 方法名
遵循驼峰命名法,最好见名知意,表达出该功能的意思即可。
④ 形参列表
a. 一个方法可以有0个参数,也可以有多个参数,中间用逗号隔开,比如:getSum(int n1,int n2)。
b. 参数类型可以为任意类型,包含基本类型或引用类型,比如:printArr(int[][] map)。
c. 方法定义时的参数成为形式参数,简称形参;方法调用时的传入参数称为实际参数,简称实参,实参和形参的类型要一致或者兼容、个数、顺序必须一致!
⑤ 方法体
里面写完成功能的具体的语句,可以为输入、输出、变量、运算、分支、循环、方法调用,但里面不能再定义方法!即方法不能嵌套定义。
⑥ 方法调用细节说明
a. 同一个类中的方法调回用:直接调用即可。
b. 跨类的方法调用:需要通过类名调用。
c. 跨类的方法调用和方法的访问修饰符相关。
(4)方法的传参机制
1. 基本数据类型的传参机制:
a方法调用b方法,给b方法传递基本数据类型,不会影响a方法中数据的值,因为基本数据类型不是引用类型,传递的是值。
2. 引用数据类型的传参机制:
a方法调用b方法,给b方法传递引用数据类型,传递的也是值,但值是地址,所以会影响a方法中数据的值。
3. 对象的传参机制:传的是地址
6、多态
(1)编译时多态性(静态绑定):重载
(2)运行时多态性(动态绑定):继承
public class SuperClass {
public void method(SuperClass obj1, SuperClass obj2) {
System.out.println("SuperClass.method(SuperClass, SuperClass)");
}
}
// SubClass.java
class SubClass extends SuperClass {
public void method(SuperClass superObj, SubClass subObj) {
System.out.println("SubClass.method(SuperClass, SubClass)");
}
public void method(SubClass subObj, SuperClass superObj) {
System.out.println("SubClass.method(SubClass, SuperClass)");
}
public void method(SubClass subObj1, SubClass subObj2) {
System.out.println("SubClass.method(SubClass, SubClass)");
}
}
public class OverloadDemo {
public static void main(String[] args) {
SuperClass superObj = new SuperClass();
SubClass subObj = new SubClass();
SuperClass superReferToSub = subObj;
superObj.method(superObj, superObj);
superObj.method(subObj, subObj);
superObj.method(superReferToSub, superReferToSub);
System.out.println("--------------------------------");
subObj.method(superObj, superObj);
subObj.method(subObj, subObj);
subObj.method(superReferToSub, superReferToSub);
System.out.println("--------------------------------");
superReferToSub.method(superObj, superObj);
superReferToSub.method(subObj, subObj);
superReferToSub.method(superReferToSub, superReferToSub);
}
}
#### 第二部分:`subObj.method(...)` 调用
- **`subObj.method(superReferToSub, superReferToSub);`**
- `superReferToSub` 是 `SuperClass` 类型的引用,但在 `SubClass` 的上下文中,它被视为 `SuperClass` 类型. 因此,调用 `SuperClass` 中的 `method(SuperClass, SuperClass)` 方法
#### 第三部分:`superReferToSub.method(...)` 调用
- `superReferToSub` 是 `SuperClass` 类型的引用,指向 `SubClass` 类型的对象.
- **`superReferToSub.method(superObj, superObj);`**
- 参数类型都是 `SuperClass`,因此调用 `SuperClass` 中的 `method(SuperClass, SuperClass)` 方法.
- **`superReferToSub.method(subObj, subObj);`**
- 尽管 `subObj` 是 `SubClass` 类型的对象,但在 `SuperClass` 的上下文中,它被视为 `SuperClass` 类型. 因此,调用 `SuperClass` 中的 `method(SuperClass, SuperClass)` 方法.
- **`superReferToSub.method(superReferToSub, superReferToSub);`**
- `superReferToSub` 是 `SuperClass` 类型的引用,因此调用 `SuperClass` 中的 `method(SuperClass, SuperClass)` 方法.
### 总结
- **静态类型的影响**:在 `SuperClass` 的上下文中,`SubClass` 类型的对象被视为 `SuperClass` 类型,因此会调用 `SuperClass` 中的方法,除非有明确的重载匹配.
7、继承
class Grandpa{
protected Grandpa(){
System.out.println("default Grandpa");
}
public Grandpa(String name){
System.out.println(name);
}
}
class Father extends Grandpa{
protected Father(){
System.out.println("default Father");
}
public Father(String grandpaName,String fatherName){
super(grandpaName);
System.out.println(fatherName);
}
}
public class Son extends Father{
public Son(){
System.out.println("default Son");
}
public Son(String grandpaName,String fatherName,String sonName) {
super(grandpaName,fatherName);
System.out.println(sonName);
}
public static void main(String args[]){
Son s1 = new Son("My Grandpa", "My Father", "My Son"); // 1
System.out.println("---------------------");
Son s2 = new Son(); // 2
}
}
子类初始化,会先调用父类的初始化函数。
-------------------------------------------------------------------------------
class Base{
String var="BaseVar";
static String staticVar="StaticBaseVar";
void method(){
System.out.println("Base method");
}
static void staticMethod(){
System.out.println("Static Base method");
}
}
public class Sub extends Base{
String var="SubVar"; // 实例变量
static String staticVar="StaticSubVar"; // 静态变量
void method(){ // 覆盖父类的method()方法
System.out.println("Sub method");
}
static void staticMethod(){ // 隐藏父类的staticMethod()方法
System.out.println("Static Sub method");
}
String subVar="Var only belonging to Sub";
void subMethod(){
System.out.println("Method only belonging to Sub");
}
public static void main(String args[]){
Base who = new Sub(); // who被声明为Base类型,引用Sub实例
System.out.println("who.var="+who.var); // who.var=BaseVar
System.out.println("who.staticVar="+who.staticVar); // who.staticVar=StaticBaseVar
who.method(); // Sub method
who.staticMethod(); // Static Base method
}
}
- `Base who = new Sub();` 创建了一个 `Sub` 类的实例,并将其赋值给 `Base` 类型的引用 `who`.
- `System.out.println("who.var="+who.var);` 输出 `who.var=BaseVar`:
- 这是因为实例变量的访问是基于引用的静态类型(即声明类型),而不是对象的实际类型。因此,`who.var` 访问的是 `Base` 类中的 `var`,而不是 `Sub` 类中的 `var`.
- `System.out.println("who.staticVar="+who.staticVar);` 输出 `who.staticVar=StaticBaseVar`:
- 静态变量的访问也是基于引用的静态类型,而不是对象的实际类型。因此,`who.staticVar` 访问的是 `Base` 类中的 `staticVar`,而不是 `Sub` 类中的 `staticVar`.
- `who.method();` 输出 `Sub method`:
- 这是因为实例方法的调用是基于对象的实际类型(多态性)。`who` 实际上指向的是 `Sub` 类的实例,因此调用的是 `Sub` 类中覆盖的 `method()` 方法.
- `who.staticMethod();` 输出 `Static Base method`:
- 静态方法的调用是基于引用的静态类型,而不是对象的实际类型。因此,`who.staticMethod()` 调用的是 `Base` 类中的 `staticMethod()` 方法,而不是 `Sub` 类中的 `staticMethod()` 方法.
### 总结
- **实例变量和静态变量的访问**:都是基于引用的静态类型(即声明类型),而不是对象的实际类型.
- **实例方法的调用**:基于对象的实际类型,表现出多态性.
- **静态方法的调用**:基于引用的静态类型,不表现出多态性.
-----------------------------------------------------------------------------------------------------
class Base {
int i;
Base() {
this.add(1);
}
void add(int v) {
i += v;
}
void print() {
System.out.println(i);
}
}
class Extension extends Base {
Extension(){
add(2);
}
void add(int v) {
i += v*2;
}
}
public class PolyTester {
public static void main(String args[]) {
bogo(new Extension());
// 以上代码创建的是Extension的实例,所以在运行时,所有调用add()方法的过程,
// 将始终和Extension类的add()方法动态绑定
// 1. 先调用父类构造:i = 0 + 1 * 2 = 2
// 2. 再调用子类构造:i = 2 + 2 * 2 = 6
// 3. 再调用bogo():i = 6 + 16 = 22
}
static void bogo(Base b) {
b.add(8);
b.print();
}
}
0214 00:00