首先解释一下“思想”。先问你个问题:你想做个怎样的人?可能你会回答:我想做个好人,孝敬父母,尊重长辈,关爱亲朋…你看,这就是思想。这是你做人的思想,或者说,是你做人的原则。做人有做人的原则,编程也有编程的原则。这些编程的原则呢,就是编程思想。
强调的是功能行为,以函数为最小单位,考虑怎么做
。面向对象,将功能封装进对象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做
。面向对象:Object Oriented Programming
面向过程:Procedure Oriented Programming
执行者
转化成了面向对象的指挥者
现实世界中的实体
。概念世界中的类
。形式计算机世界中类的定义
。即借助某种程序语言,把类构造成计算机能够识别和处理的数据结构。类实例化成计算机世界中的对象
。对象是计算机世界中解决问题的最终工具。类(Class)和对象(Ojbect)
是面向对象的核心概念。
/**
* 一、设计类,其实就是设计类的成员
* 属性 = 成员变量 = filed = 域、字段
* 方法 = 成员方法 = 函数 = method
* 创建类的对象 = 类的实例化 = 实例化类
*
* 二、类和对象的使用(面向对象思想的落地实现)
* 1、创建类,设计类的成员
* 2、创建类的对象
* 3、通过 “对象.属性” 或 “对象.方法” 调用对象的结构
*
* 三、如果创建了一个类的多个对象,则每个对象都独立的拥有一套类的属性。(非static的)
* 意味着:我们修改一个对象的属性a,则不影响另外一个对象属性a的值
*
* 四、对象的内存解析
*/
public class PeopleTest {
public static void main(String[] args) {
//2、创建People类的对象
People people = new People();
//3、调用对象的结构:属性、方法
//调用属性:“对象.属性”
people.name = "张三";
people.isMale = true;
System.out.println(people.name);
//调用方法:“对象.方法”
people.eat();
people.sleep();
people.talk("Chinese");
People people1 = new People();
System.out.println(people1.name);
System.out.println(people1.isMale);
//将people保存的对象地址值赋给people1,导致people和people1指向了堆空间中的同一个对象的实体。
People people2 = people;
System.out.println(people2.name);//张三
people2.age = 10;
System.out.println(people.age);//10
}
}
//1、创建类,设计类的成员
class People{
//属性
String name;
int age;
boolean isMale;
//方法
public void eat(){
System.out.println("人可以吃饭");
}
public void sleep(){
System.out.println("人可以睡觉");
}
public void talk(String language){
System.out.println("人可以说话,使用的语言是:" + language);
}
}
说明:如果创建了一个类的多个对象,对于类中定义的属性,每个对象都拥有各自的一套副本,且互不干扰。
//2、创建People类的对象
People people = new People();
people.name = "张三";
people.isMale = true;
System.out.println(people.name);
People people1 = new People();
System.out.println(people1.name);
System.out.println(people1.isMale);
//将people保存的对象地址值赋给people1,导致people和people1指向了堆空间中的同一个对象的实体。
People people2 = people;
System.out.println(people2.name);//张三
people2.age = 10;
System.out.println(people.age);//10
Person p1 = new Person();//执行完后的内存状态。其中类定义如下:
class Person {
int age;
void shout() {
System.out.println("oh my god! I am " + age);
}
}
class PersonTest {
public static void main(String[] args) {//程序运行的内存布局如下图
Person p1 = new Person();
Person p2 = new Person();
p1.age = -30;
p1.shout();
p2.shout();
}
}
堆(Heap)
,此内存区域的唯一目的就是存放对象实例
,几乎所有的对象实例都在这里分配内存。这一点在Java虚拟机规范中的描述的是:所有的对象实例以及数组都要在堆上分配。栈(Stack)
,是指虚拟机栈。虚拟机栈用于存储局部变量等
。局部变量表存放了编译器可知长度的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型,它不等同于对象本身,是对象在堆内存的是首地址)。方法执行完,自动释放。方法区(Method Area)
,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码
等数据。修饰符 数据类型 属性名 = 初始化值;
修饰符:常用的权限修饰符有:private、缺省、protected、public
数据类型:任何基本类型(如int、Boolean)或任何引用类型
属性名:属于标识符,符合命名规则和规范即可。
成员变量 | 局部变量 | |
---|---|---|
声明的位置 | 直接声明在类中 | 方法形参或内部、代码块内、构造器内等 |
修饰符 | private、public、static、final等 | 不能用权限修饰符修饰,可以用final修饰 |
初始化值 | 有默认初始化值 | 没有默认初始化值,必须显示赋值,方可使用 |
内存加载位置 | 堆空间或静态域内 | 栈空间 |
public class Person {
private int age;
public int getAge() { //声明方法getAge()
return age;
}
public void setAge(int i) {//声明方法setAge
age = i;//将参数i的值赋给类的成员变量age
}
}
修饰符 返回值类型 方法名(参数类型 形参1, 参数类型 形参2,...) {
方法体程序代码
return 返回值;
}
修饰符:public、缺省、private、protected等
返回值类型
方法名:属于标识符,命名时遵循标识符命名规则和规范,“见名知意”
形参列表:可以包含零个,一个或多个参数。多个参数时,中间用“,”隔开
按照是否有形参及返回值
无返回值 | 有返回值 | |
---|---|---|
无形参 | void 方法名 () { } | 返回值的类型 方法名 () { } |
有形参 | void 方法名 (形参列表) { } | 返回值的类型 方法名 (形参列表) { } |
注 意:
方法被调用一次,就会执行一次
没有具体返回值的情况,返回值类型用关键字void表示,那么方法体中可以不必使用return语句。如果使用,仅用来结束方法。
定义方法时,方法的结果应该返回给调用者,交由调用者处理。
方法中只能调用方法或属性,不可以在方法内部定义方法。
return关键字的使用
Java生成[a, b]之间的随机整数公示推导
推导公式:(int)(Math.random() * (b-a+1) + a) 取值范围在[a, b]中
推导过程:
证明:
① 因为Math.random()取值范围在[0,1)内
所以 Math.random()*b 取值范围在[0, b)内
② 又因为证明的(int)(Math.random() * (b-a+1) + a) 取值范围在[a, b]中 b为闭区间,
int取的是整数部分
所以(int)(Math.random()*b)取值范围在[0, b-1]区间内
③ 又因为(int)(Math.random()*b + a) 取值范围在[a, b-1+a]范围内
此时将b用b-a+1替换得(int)(Math.random()*(b-a+1) + a) 取值范围在[a, b]范围内
④ 所以最终证明 (int)(Math.random() * (b-a+1) + a) 取值范围在[a, b]中
在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可
。参数个数或者参数类型
)。调用时,根据方法参数列表的不同来区别。//返回两个整数的和
int add(int x, int y){return x+y;}
//返回三个整数的和
int add(int x, int y, int z){return x+y+z;}
//返回两个小数的和
double add(double x, double y) {return x+y;}
//JDK 5.0以前:采用数组形参来定义方法,传入多个同一类型变量
public static void test(int a, String[] books);
//JDK 5.0:采用可变个数形参来定义方法,传入多个同一类型变量
public static void test(int a ,String... books);
下面两者只能存在一个
public static void SyoutNumber(int[] nums) {
for (int i = 0; i < nums.length; i++) {
System.out.println("nums[i] = " + nums[i]);
}
}
public static void SyoutNumber(int... nums) {
for (int i = 0; i < nums.length; i++) {
System.out.println("nums[i] = " + nums[i]);
}
}
可变个数形参在方法的形参中,必须声明在末尾
。可变个数形参在方法的形参中,最多只能声明一个可变形参
。值传递
。即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。
数据值
”传递给形参。地址值
”传递给形参。public class TransferTest3 {
public static void main(String[] args) {
TransferTest3 test = new TransferTest3();
test.first();
}
public void first() {
int i = 5;
Value v = new Value();
v.i = 25;
//该val在second调用过后,就会别垃圾回收机制回收
second(v, i);
//此时的v表示的是本方法中的Value对象
System.out.println(v.i);//v.i = 20
}
public void second(Value v, int i) {
i = 0;
v.i = 20;
Value val = new Value();
v = val;
System.out.println(v.i + " " + i);//v.i=15 i=0
}
}
class Value {
int i = 15;
}
public class ValueTransferTest {
public static void main(String[] args) {
//成员变量存储在静态域或者堆空间
//局部变量存储在栈中
String s1= "hello";
String s2 = new String("hello2");
ValueTransferTest test = new ValueTransferTest();
test.change(s1);
System.out.println("s1 = " + s1);//hello~~
test.change(s2);
System.out.println("s2 = " + s2);//hello2~~
int num = 10;
test.changeInt(num);
System.out.println(num);//10
}
public void change(String s) {
s = "hi~~";
}
public void changeInt(int s) {
s = 265;
}
}
public static void main(String[] args) {
int a = 10;
int b = 10;
//method(a, b);
method2(a, b);
System.out.println("main... a = " + a);
System.out.println("main... b = " + b);
}
/**
* @description:
* @author: cjw
* @date: 2023/8/11 13:11
* @param: []
* @return: void
* 方法一:在method方法中进行输出
**/
public static void method(int a, int b) {
a = a * 10;
b = b * 10;
System.out.println("method... a = " + a);
System.out.println("method... b = " + b);
System.exit(0);
}
/**
* @description:
* @author: cjw
* @date: 2023/8/11 13:19
* @param: [a, b]
* @return: void
* 方法二: 重写输出方法
**/
public static void method2(int a, int b) {
PrintStream ps = new PrintStream(System.out) {
@Override
public void println(String s) {
if ("main... a = 10".equals(s)) {
s = "main... a = 100";
} else if ("main... b = 10".equals(s)) {
s = "main... b = 100";
}
super.println(s);
}
};
System.setOut(ps);
}
/*
* 定义一个int型的数组:int[] arr = {12, 3, 3, 34, 56, 77, 432}
* 让数组的每个位置上的值去除以首位置的元素,得到的结果,作为该位置上的新值。遍历新的数组
*/
public static void main(String[] args) {
int[] arr = {12, 3, 3, 34, 56, 77, 432};
//arrayInversion(arr);
//arrayInversionOne(arr);
arrayInversionTwo(arr);
System.out.println(Arrays.toString(arr));
}
public static void arrayInversion(int[] arr) {
int flag = arr[0];
for (int i = arr.length - 1; i >= 0; i--) {
arr[i] /= flag;
// System.out.println("arr["+i+"] = " + arr[i]);
}
}
public static void arrayInversionTwo(int[] arr) {
int flag = arr[0];
for (int i = 0; i < arr.length; i++) {
arr[i] /= flag;
}
}
public static void arrayInversionOne(int[] arr) {
for (int i = arr.length - 1; i >= 0; i--) {
arr[i] /= arr[0];
}
}
public static void testD() {
int[] a= new int[5];
System.out.println(a);
char[] b = new char[3];
System.out.println(b);
}
public static void testE() {
int[] a= new int[]{0,1,2};
System.out.println(a);
char[] b = new char[]{'a','b','c'};
System.out.println(b);
}
递归方法:一个方法体内调用它自身。
/*
* @description:给定一个数据n,返回1~n之间所有数据的和
**/
public static void main(String[] args) {
System.out.println("请开始输入数据================》");
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
int n = scanner.nextInt();
if (n == 0) {
System.exit(0);
}
System.out.println("自然数和为:" + getSum(n));
}
}
public static int getSum(int n) {
if (n == 1) {
return 1;
}
return n + getSum(n-1);
}