public class Cat {
public static void main(String[] args) {
// 如何实例化一个对象
// 1. new Catt(); 创建一只猫
// 2. Catt cat1 = new Catt(); 把创建的猫赋给cat1
Catt cat1 = new Catt();
cat1.name = "abc";
cat1.age = 3;
cat1.color = "white";
// 如何访问对象的属性
System.out.println("第一只猫的信息" + cat1.name + " " + cat1.age + " " + cat1.color);
}
}
class Catt {
String name;
int age;
String color;
}
class Catt {
String name; // name,age,color即为成员变量
int age;
String color;
String[] master; //属性可以是基本数据类型,也可以是引用数据类型(对象,数组)
}
Catt cat = new Catt();
1.属性的定义语法同变量:访问修饰符 + 属性范围 + 属性名;
先声明再创建
Cat cat; //先声明,声明的时候没有分配内存空间
cat = new Cat(); //再创建,分配内存空间,实例化
直接创建
Cat cat = new Cat(); // 类的类型就是实例化的类的类型
声明格式:定义变量的类 + 定义变量的名字
基本语法:对象名.属性名
用 . 来取对象中的属性
Person a = new Person();
a.age = 10;
a.name = "小明";
Person b;
b = a; //
b.age = 200;
b.name = null; //将b在栈中的指向地址置为空,也就是说,原来a和b都指向堆中的同一个地址的指针,b断掉了
System.out.println(a.age); // 这个时候输出a.age是经过b.age修改之后的200
System.out.println(b.age); // 这个时候输出b.age会出现异常
public class Method01 {
public static void main(String[] args){
//方法使用
//1. 方法写好后,不去显式调用不会使用方法
//2. 先创建对象,创建对象后和调用属性的方式相同调用方法
for(int i = 0;i < 100; i ++){
Person p1 = new Person();
p1.speak();
}
}
}
class Person {
String name;
int age;
// public 表示方法是公开的
// void 表示方法没有返回值
// {} 大括号内是方法体,嵌入执行代码
public void speak() {
System.out.println("abc");
}
}
public class Method02 {
public static void main(String[] args){
Person p1 = new Person();
p1.cal01();
p1.cal02(5); //调用cal02方法,并且将5传给cal02fan
}
}
class Person {
public void cal01()
{
int res = 0;
for (int i = 1; i < 1000; i++) {
res += i;
}
System.out.println("计算结果" + res);
}
public void cal02(int n){ // (int n) 形参列表,表示当前有一个形参n,可以接受用户输入
int res = 0;
for(int i = 0;i <= n;i++){
res += i;
}
System.out.println("res的结果为" + res);
}
}
import java.util.Scanner;
public class Method02 {
public static void main(String[] args){
Person p1 = new Person();
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
p1.cal01();
p1.cal02(n); //调用cal02方法,并且将5传给cal02方法
}
}
class Person {
public void cal01()
{
int res = 0;
for (int i = 1; i < 1000; i++) {
res += i;
}
System.out.println("计算结果" + res);
}
public void cal02(int n){ // (int n) 形参列表,表示当前有一个形参n,可以接受用户输入
int res = 0;
for(int i = 0;i <= n;i++){
res += i;
}
System.out.println("res的结果为" + res);
}
}
public int getSum(int num1,int num2){ //(int num1.int num2)形参列表,2个形参,可以接受用户传入的两个数
int res = num1 + num2;
return res; //表示把res的值,返回
}
public class Method03 {
public static void main(String[] args) {
Tools tool = new Tools();
int[][] map = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
int res = tool.getSum(map);
System.out.println(res);
}
}
class Tools {
public int getSum(int[][] map) {
int res = 0;
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[i].length; j++) {
res += map[i][j];
}
}
return res;
}
}
访问修饰符[public private protected] 返回数据类型[void int ...] 方法名 (形参列表){
//方法体语句
return 返回值;
}
一个方法最多返回一个值
如果想要返回多个结果,则需要返回一个数组,将结果封装到一个数组中去 (即将返回值设为int[]等数组类型)
public class MethodDetail {
public static void main(String[] args) {
AA a = new AA();
int[] res = a.getSumAndSub(1, 2);
System.out.println("sum=" + res[0]);
System.out.println("sub=" + res[1]);
}
}
class AA{
public int[] getSumAndSub(int num1,int num2){
int[] res = new int[2];
res[0] = num1 + num2;
res[1] = num1 - num2;
return res;//这个地方res是一个数组,所以应该返回一个地址
}
}
返回类型可以为任意类型,包括基本数据类型和引用类型(数组,对象)
返回值类型必须和return的值类型一致或兼容
void的返回值可以写return,此时return后面不能带任何东西,默认return值为空
同一个类中的方法调用,可以直接调用
public class Method03 {
public static void main(String[] args) {
A a = new A();
a.sayOk();
}
}
class A {
public void print(int n) {
System.out.println("print方法被调用" + n);
}
public void sayOk() {
print(10);
}
}
跨类中的方法A类调用B类方法:需要通过对象名调用(即在A类中再实例化一个变量B)
public class Method03 {
public static void main(String[] args) {
A a = new A();
a.sayOk();
a.m1();
}
}
class A {
public void print(int n) {
System.out.println("print方法被调用" + n);
}
public void sayOk() {
print(10); //这个地方没有使用.去对象名调用,因为这个函数的定义在同一个类中
}
public void m1(){
System.out.println("m1方法被调用");
B b = new B();
b.hi(); //这个地方进行了对象名调用,因为方法的定义不在同一个类中
}
}
class B{
public void hi(){
System.out.println("B类中的hi()被执行");
}
}
```java public class Caculation01 {
public static void main(String[] args) {
Mycaculator m1 = new Mycaculator();
System.out.println(m1.calculate(1.1, 2.2));
System.out.println(m1.calculate(1, 2));
}
}
class Mycaculator {
public int calculate(int n1, int n2) { // 如果只是参数名不同则不能构成重载
return n1 + n2;
}
public double calculate(int n1, double n2) {
return n1 + n2;
}
public double calculate(double n1, double n2) {
return n1 + n2;
}
}
3. 参数顺序不一样也是重载,先int后double 和 先double后int不同
### 方法重载的细节
1. 方法名必须相同
2. 参数列表:必须不同(形参**类型**或**个数**或**顺序**,**至少有一样不同**,**参数名无要求**)
3. **返回类型不要求**(如果只是返回类型不同而其它都相同,则不构成重载)
4. 能否构成重载,就看**在编译的时候是否报错**即可,如果报**已经定义了这个方法**的错误,就不构成重载
## 可变参数
1. java允许将同一个类中多个**同名同功能**但是参数个数不同的方法,封装成一个方法
2. ```java
public class Var{
public static void main(String[] args){
HspMethod m1 = new HspMethod();
System.out.println(m1.sum());
}
}
class HspMethod{
public int sum(int... nums){
//1. ...表示接受的是可变参数,类型是int,即可以接受多个int(0-多),int... nums,int... nums
//2. 使用可变参数时,可以当作数组来使用,即nums可以当作数组,即nums可以取下标,当作数组去处理
//3. 遍历nums求和即可
int res = 0;
for(int i = 0;i < nums.length;i++){ //因为可变参数的参数类型可以当作数组去处理,所以可以取length
res += nums[i];
}
return res;
}
}
上面的可以通过重载来实现(函数名相同,但是参数不同)
也可以使用可变参数:方法名称相同,功能相同,参数个数不同 -> 使用可变参数优化
访问修饰符 返回类型 方法名(数据类型... 形参名){}
[修饰符] 方法名(形参列表){
方法体
}
public class Test02 {
public static void main(String[] args) {
// 当new一个对象时,直接通过构造器指定名字和年龄
// 在new的时候直接传参,可以使用构造器
Person p1 = new Person("smith", 80);
// 构造器在被调用的时候,对象应该已经被创建了
}
}
class Person {
String name;
int age;
public Person(String pname, int page) {
System.out.println("yes");
name = pname;
age = page;
}
}
javap时jdk提供的一个命令行工具,Javap能对给定的class文件提供字节代码进行反编译
通过它,可以查看到源代码
格式:
javap xxx.class 或者 javap xxx (可以不带.class)
-c 对代码进行反汇编
-v 输出附加信息
-p 显式所有类和成员
package com.hspedu; package 包的名字;
将属性私有化 private 不能直接修改属性
提供一个公共的set方法,用于对属性进行判断并且赋值
public void setXxx(类型 参数名){
//加入数据验证的业务逻辑
如果通过则
属性=参数名
}
提供要给公共的get方法,用于获取属性的值
public 数据类型 getXxx(){
//权限判断
}
构造器的形参,如果能够直接写成属性名
public Dog(String name,int age){
name = name;
age = age;
}
但是出现了一个问题,根据变量的作用域原则,构造器的name是局部变量,而不是属性,构造器的age也是局部变量,而不是属性
这样做相当于是name局部变量又赋值给了它本身,没有用处,当这个构造器结束时,局部变量的作用域一结束,就什么都没了
public Dog(String name,int age){
//所以上面的name和age应该加上this,this.age就是当前对象的属性age
this.name = name;
this.age = age;
}
指定地去调用父类的某个构造器,则需要显式的调用
```java super(参数列表)
3. 调用父类中的**无参构造器**,super()中的参数什么都不写,默认调用super()
#### 第五:super的使用
1. super在使用时,**必须放在构造器的第一行**
2. super关键字**只能在构造器中使用,不能在普通成员方法中使用**
#### 第六:
1. super()和this()都只能放在构造器的第一行,因此这两个方法不能共存在一个构造器
#### 第七:object类
1. Java所有类都是Object的子类,Object是所有类的基类
2. 按住 **ctrl + h** 可以看到所有类的父子关系
3. 
4. 如果new了最后一个子类,会**一级一级地调用上一级的构造器**,直到**调用到了顶级父类的构造器**,**Object类**
5. 
#### 第九:单继承
1. 子类最多**只能继承一个父类**,即Java中式**单继承机制**
2. 如果想让A继承B和C,则可以让**A继承B,B继承C**
#### 第十:不能滥用继承
1. 不能滥用继承,子类和父类之间必须满足 **is-a** 的逻辑关系
2. 
## super
### 概念
1. super代表父类的引用,用于访问父类的属性,方法,构造器
### 具体用法
1. 访问父类的属性,但是不能访问父类的private属性,可以
```java
super.属性名
访问父类的方法,不能访问父类的private方法
super.方法名(参数列表);
调用父类的构造器(因为只有一个父类,所以不需要加父类的名字就可以区分),当参数不同时,调用语法:
super(参数);
package Override;
public class Override01 {
public void cry(){
System.out.print("动物叫唤");
}
}
//父类
package Override;
public class Dog extends Override01 {
public void cry() {
System.out.print("小狗汪汪叫");
}
}
//子类
方法重写也叫方法覆盖,需要满足下面的条件
子类的方法的参数,方法名称,要和父类方法的参数,方法名称完全一样,否则不构成重写
子类方法的返回类型和父类一样,或者,是父类返回类型的子类,比如父类返回类型是Object,子类方法返回类型是String
```java
public Object cry() {
return null;
}//父类
public String cry(){
return null;
}//子类
5. 否则会报错
6. 子类方法不能缩小父类方法的访问权限 public -> protected -> 默认 -> private
7. 也就是说,返回类型可以细化,但是访问范围不能缩小
8. 例如:父类中为public , 子类中为private,则会报错
9. 
## 多态polymorphic
### 解决的问题
1. 
```java
package A;
public class Master {
private String name;
public Master(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//给小狗吃骨头
public void feed(Dog dog,Bone bone){ //这个地方的参数,和int a一样,只是声明了数据类型和变量名
System.out.print("主人" + name + "给" + dog.getName() + "吃" + bone.getName());
}
//给小猫吃🐟,和给狗吃骨头构成重载
public void feed(Cat cat,Fish fish){
System.out.print("主人" + name + "给" + cat.getName() + "吃" + fish.getName());
}
//如果有很多动物和食物,会导致feed重载量很大
}
package A;
public class Poly01 {
private String name;
public Poly01(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public void setName(String name){
this.name = name;
}
}
class Fish extends Poly01{
public Fish(String name){
super(name);
}
}
class Bone extends Poly01{
public Bone(String name){
super(name);
}
}
package A;
public class Animal {
private String name;
public Animal(String name){
this.name = name;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
}
class Cat extends Animal{
public Cat(String name) {
super(name);
}
}
class Dog extends Animal{
public Dog(String name) {
super(name);
}
}
编译时,javac,类型由声明该变量时使用的类型决定
运行时,java,类型由实际赋给该变量的对象决定
```java Person p = new Women(); //Women继承自Person类
4. 上面的p会得到Person类的属性,调用Women类的方法
5. 
6. 可以理解为:编译类型决定了变量的属性,而运行类型决定了方法
### 使用多态机制,可以统一的管理主人喂食的问题
## 抽象方法
### 处理问题:
1. 处理的主要问题是:父类方法的不确定性问题
2. 
3. 考虑将该方法设计为抽象(abstract)方法
4. 所谓抽象方法就是没有实现的方法,所谓没有实现,就是没有方法体
5. 当遇到
6. ```java
Missing method body , or declare abstract
时,说明如果没有方法体,可以声明为一个抽象方法
抽象方法只需要声明即可
```java public abstract void eat(); 限制范围 abstract 返回值类型 函数名();
10. 将一个类做成抽象类,并让子类去具体实现,父类只是起到一个声明的作用
11. 一般来说,抽象类会被继承,由其子类来继承
### 抽象类细节
1. 用abstract关键字来修饰一个类时,这个类就叫做抽象类
2. ```java
访问修饰符 abstract 类名{
//属性
//方法
public abstract void eat(){}
}
用abstract关键字来修饰一个方法时,这个方法就是抽象方法,
```java 访问修饰符 abstract 返回类型 方法名(参数列表); //后面不能加方法体,否则会报abstract methods cannot have a body
5. 抽象类的**价值更多作用在于设计**,是设计者设计好后,让**子类继承并实现**
6. 后面的**接口**是很常见的抽象类调用
7. 抽象类不能被实例化
8. 
9. **抽象类不一定要包含abstract方法**,也就是说,抽象类可以没有abstract方法。抽象类中还可以有实现的方法
10. 
11. **一旦一个类包含了abstract方法,则这个类必须声明为abstract**(但是一个abstract类中不一定包含abstract方法)
12. **抽象类可以有任意成员** [抽象类的**本质还是类**] ,比如:非抽象方法,构造器,静态属性等等
13. 抽象方法不能有主体,即不能实现
14. 如果**一个类继承了抽象类**,则它**必须实现抽象类的所有抽象方法**,**除非它自己也声明为abstract类**
15. 
### abstract修饰的对象
1. abstract只能修饰类和方法
2. abstract不能修饰属性和其它,抽象的属性说不通
3. 
## 接口interface
### 快速入门
1. usb插槽就是现实的接口
2. 不用担心哪个插槽是插哪个的,因为做usb插槽的厂家和做各种设备的厂家都遵守了统一的规定,包括尺寸,排线等等
3. 程序就是一个世界
### 实现思路
1. 实现接口,就是把接口方法实现
2. 接口方法就是一个标准,类似于USB2.0和USB3.0
### 概念
1. **接口就是给出一些没有实现的方法**,封装到一起,到某个类**要使用的时候**,再根据**具体情况把这些方法写出来**
2. ```java
访问范围修饰符 interface 接口名{
//属性
//方法,这个时候方法只有方法名,没有方法体的具体实现
}
class 类名 implements 接口{
//自己属性
//自己方法,这个时候可以根据具体情况加上类的调用
//必须实现的接口的抽象方法
}
在接口中,抽象方法,可以省略abstract关键字
implement关键字用来调用接口,生效,执行,实施
在jdk8后,可以有默认实现方法,需要使用default关键字修饰
default public void ok(){
}
在jdk7.0前,接口里所有方法都没有方法体,即都是抽象方法
在jdk8.0以后,接口可以有静态方法,默认方法,也就是说接口中可以有方法的具体实现
定义所有对象共享的变量即为类变量
```java 类名.变量名 Child.count 或者也可以 实例化的对象.变量名 child1.count
4. 可以**直接由类名访问**,因为是类变量
5. 也可以由**实例化的对象进行类变量的访问**,因为这几个对象出自一个类,所以 这几个对象的变量是**共享的**
6. 
### 什么是类变量
1. **类变量也叫静态变量,静态属性,是该类的所有对象共享的变量,任何一个该类的对象去访问它时,取到的值都是相同的值,同样,任何一个该类的对象去修改它时,修改的也是同一个变量**
2. ```java
访问修饰符 static 数据类型 变量名;
访问类变量:类名.类变量名 或者 对象名.类变量名
类变量并不依赖于实例,类变量是随着类的加载而创建的,所以没有创建对象实例也可以访问
```java public class lei {
public static void main(String[] args){
//这个地方是通过 类名.变量名 去访问的,类变量
sta.a++;
System.out.print(sta.a);
}
}
class sta{
public static int a = 0;
}
### 类变量使用细节
#### 使用类变量的时候
1. 在需要**这个类的所有对象都能访问**到这个变量的时候就需要使用类变量(共享一个变量)
2. 
#### 类变量和实例变量的区别
1. 类变量是该类的**所有对象共享的**,而实例变量是**某个对象独享的**
2. 实例对象如果没有实例化则不能访问
3. 类变量如果没有实例化仍可以访问
#### 加上static称为类变量或者静态变量,否则称为实例变量、普通变量、非静态变量
#### 推荐使用 类名.类变量名 来访问
### 类变量的生命周期
1. 类变量的声明周期是**随着类的加载开始,随着类的消亡而毁灭**
2. 只要类没有消亡,类变量就不会消亡
## 类方法
### 静态方法
1. ```java
访问修饰符 static 数据返回类型 方法名(){}
当方法使用了static修饰后,该方法就是静态方法
静态方法就可以访问静态属性/变量
public static void main(String[] args){}
java ListNode链表是用Java自定义实现的链表结构
```java class ListNode{
int val;
ListNode next;
}
4. 添加构造方法,方便初始化
```java
class ListNode{
int val;
ListNode next;
ListNode(int val){
this.val = val;
}
}
删除一个节点
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public void deleteNode(ListNode node) {
ListNode p = node.next;
node.val = p.val;
node.next = p.next;
}
}
@RequestMapping可以将HTTP请求映射到某个类中的方法
@RequestMapping(value = "/ex/foos", method = RequestMethod.GET)
@ResponseBody
public String getFoosBySimplePath() {
return "Get some Foos";
}
//value值写路径,method写方法
详细参数看(100条消息) SpringMVC-@RequestMapping的参数和用法_流烟默的博客-CSDN博客_@requestmapping
最重要的参数:value=”url”,method= RequestMethod.POST/RequestMethod.GET