10、重写(overwrite) 和 重载(overload): 15
Java基础:
1、java基础语法:
类:软件工程的思想上来看,类是对现实世界中一组具有共同特征的事物的抽象。
对象:对象是一个类的具体实例。
方法:是Java语句的集合,集中在一起实现指定的功能,类似于C/C++中的函数,但一个是面向对象的思想方法,一个是面向结构的思想方法。
方法是解决一类问题的步骤的有序组合
方法包含于类或对象中
方法在程序中被创建,在其他地方被引用
一般语法:
修饰符 返回值类型 方法名(参数类型 参数名){ //参数列表
...
方法体
...
return 返回值;
}
成员变量:在类的变量部分定义的变量,也被成为属性。
C:\Users\Administrator>cd C:\Users\Administrator\Desktop\helloworld\src
C:\Users\Administrator\Desktop\helloworld\src>javac TestMain.java
C:\Users\Administrator\Desktop\helloworld\src>java TestMain
结果:
test
123
hello test 123
C:\Users\Administrator\Desktop\helloworld\src>cd C:\Users\Administrator\Desktop\hello
C:\Users\Administrator\Desktop\hello>g++ hello.cpp -o hello.out
C:\Users\Administrator\Desktop\hello>hello.out
结果:
123
如果是多个 C++ 代码文件,如 runoob1.cpp、runoob2.cpp,编译命令如下:
$ g++ runoob1.cpp runoob2.cpp -o runoob
生成一个 runoob 可执行文件。
类名、方法名、变量名、常量名等 驼峰命名法,大小写等
标识符通常由字母和数字以及其它字符构成。
访问修饰符:public private protected default
非访问修饰符:static final
参考菜鸟教程(尤其注意非访问修饰符的使用):
https://www.runoob.com/java/java-modifier-types.html
byte
short
int
long
float
double
char
boolean
不再赘述。
基本数据类型的数据,使用起来非常的方便,但是没有对应的方法来操作这些数据。
所以我们可以使用一个类,把基本类型的数据包装起来,这个类叫包装类。
在包装类中可以定义一些方法,用来操作基本类型的数据。
基本类型与对应的包装类:
需要注意的是装箱与拆箱的概念以及自动拆箱与自动装箱(JDK1.5之后。)
floor() round()(四舍五入) ceil() random()。
例:
public class NumberAndMath {
public static int randomNum(int max,int min){
return (int)Math.floor(Math.random()*(max-min+1)+min);
}
public static void main(String[] args){
//这里数据量展示不作太多:
//向下取整:
System.out.println("Math.floor(1.1):"+Math.floor(1.1));
//向上取整:
System.out.println("Math.ceil(1.1):"+Math.ceil(1.1));
//四舍五入:
System.out.println("Math.round(1.1):"+Math.round(1.1));
//产生一个[0,1)之间的随机数(浮点数)
System.out.println("Math.random():"+Math.random());
//testRandom():
//产生一个20-100的随机数:
double num=Math.random(); //产生[0,1)的double类型的随机数
double num1=num*80+20; //此时产生了从[20,100)的double类型的随机数
System.out.println("testRandom():"+num1);
//采用向下取整(其实采用此种方式不能取到100)
System.out.println("采用向下取整:testRandom():"+(int)Math.floor(num1));
//调用函数封装:
System.out.println("调用函数:testRandom():"+randomNum(80,20));
}
}
结果:
Math.floor(1.1):1.0
Math.ceil(1.1):2.0
Math.round(1.1):1
Math.random():0.3530030287473128
testRandom():92.94864892778125
采用向下取整:testRandom():92
调用函数:testRandom():34
上面已经提及。
加减乘除等 A++(先运算后+1)与++A(先+1后运算)
例:
int a=3;
int b=3;
System.out.println("a++:"+(a++));
System.out.println("++b:"+(++b));
结果:
a++:3
++b:4
while(判断条件){方法体}
do{方法体}while(判断条件)
for(初始化; 布尔表达式; 更新) {
//代码语句
}
例如打印九九乘法表:
//for循环九九乘法表:
for(int i=1;i<10;i++)
{
for(int j=1;j<=i;j++){
System.out.print(j+"*"+i+"="+i*j+" ");
}
System.out.println("");
}
结果:
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
冒泡排序:
//冒泡排序:
int[] arr = {1, 2, 4, 5, 3, 9, 8, 7, 6, 0};
int num;
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1; j++) {
if (arr[j] < arr[j + 1]) {
num = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = num;
}
}
}
for (int i = 0; i < arr.length; i++) {
System.out.print(i + " ");
}
System.out.println();
结果:
0 1 2 3 4 5 6 7 8 9
6、数组:
例:
//数组作为函数的参数:
public static void printArray(double[] array) {
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
}
//返回参数为数组:
public static int[] reverse(int[] list) {
int[] result = new int[list.length];
for (int i = 0, j = result.length - 1; i < list.length; i++, j--) {
result[j] = list[i];
}
return result;
}
//数组定义(Java语法):
System.out.println("数组定义(Java语法):");
double[] a={1,2,3,4,5};
for(int i=0;i<a.length;i++){
System.out.print(a[i]+" ");
}
System.out.println();
//数组定义(C/C++风格)(在Java中也能使用,但是不建议这样做):
System.out.println("数组定义(C/C++风格):");
double b[]={1,2,3};
for(int i=0;i<b.length;i++){
System.out.print(b[i]+" ");
}
System.out.println();
//未赋值,输出为null:
System.out.println("未赋值,输出为null:");
String[] s = new String[3];
for(int i=0;i<s.length;i++){
System.out.println(s[i]);
}
//对于循环,JDK1.5引入了for-each循环:
/*
for(type element: array)
{
System.out.println(element);
}
*/
System.out.println("for-each:");
for(double i: a)
{
System.out.print(i+" ");
}
System.out.println();
//数组作为函数的参数:
System.out.println("数组作为函数的参数:");
printArray(b);
System.out.println();
//数组作为函数的参数且返回参数为数组逆序并通过for-each遍历循环数组:
System.out.println("数组作为函数的参数且返回参数为数组逆序:");
int[] reservetest = reverse(new int[]{1,2,3});
for(double i: reservetest)
{
System.out.print(i+" ");
}
}
结果:
数组定义(Java语法):
1.0 2.0 3.0 4.0 5.0
数组定义(C/C++风格):
1.0 2.0 3.0
未赋值,输出为null:
null
null
null
for-each:
1.0 2.0 3.0 4.0 5.0
数组作为函数的参数:
1.0 2.0 3.0
数组作为函数的参数且返回参数为数组逆序:
3.0 2.0 1.0
7、封装:
封装,即隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别;将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中数据和函数都是类的成员。
8、继承:
继承:子类(派生类)继承父类(基类)的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
extends(普通类或抽象类)或implement(接口)
注意super,this,final(不可继承)等关键字。
抽象类:
通常在编程语句中用 abstract 修饰的类是抽象类。在C++中,含有纯虚拟函数的类称为抽象类,它不能生成对象;在java中,含有抽象方法的类称为抽象类,同样不能生成对象。
例(抽象类和抽象方法):
public abstract class Employee
{
private String name;
private String address;
private int number;
public abstract double computePay(); //抽象方法
//其余代码
}
抽象类是不完整的,它只能用作基类。
接口:
Java里面由于不允许多重继承,所以如果要实现多个类的功能,则可以通过实现多个接口来实现。(同时保证了一定的安全性和信息隐藏,比如我们使用的API等接口,对我们隐藏了实现细节,保留接口供我们使用。)
语法格式:
[可见度] interface 接口名称 [extends 其他的接口名] {
// 声明变量
// 抽象方法
}
抽象类与接口对比:
参数 | 抽象类 | 接口 |
默认的方法实现 | 它可以有默认的方法实现 | 接口完全是抽象的。它根本不存在方法的实现 |
实现 | 子类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现。 | 子类使用关键字implements来实现接口。它需要提供接口中所有声明的方法的实现(若实现类是abstract的也不需要全部实现) |
构造器 | 抽象类可以有构造器 | 接口不能有构造器 |
与正常Java类的区别 | 除了你不能实例化抽象类之外,它和普通Java类没有任何区别 | 接口是完全不同的类型 |
访问修饰符 | 抽象方法可以有public、protected和default这些修饰符 | 接口方法默认修饰符是public。你不可以使用其它修饰符。 |
main方法 | 抽象方法可以有main方法并且我们可以运行它 | 接口没有main方法,因此我们不能运行它。 |
多继承 | 抽象方法可以继承一个类和实现多个接口 | 接口只可以继承一个或多个其它接口 |
速度 | 它比接口速度要快 | 接口是稍微有点慢的,因为它需要时间去寻找在类中实现的方法。 |
添加新方法 | 如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。 | 如果你往接口中添加方法,那么你必须改变实现该接口的类。 |
9、多态:
多态性是允许你将父对象设置成为一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说:允许将子类类型的指针赋值给父类类型的指针。多态性在Object Pascal和C++中都是通过虚函数实现的。
虚函数的存在是为了多态。
对于Java来说:
Java 中其实没有虚函数的概念,它的普通函数就相当于 C++ 的虚函数,动态绑定是Java的默认行为。如果 Java 中不希望某个函数具有虚函数特性,可以加上 final 关键字变成非虚函数。
例(C++):
#include<iostream>
using namespace std;
class A
{
public:
virtual void print()
{
cout<<"This is A"<<endl;
}
};
class B : public A
{
public:
virtual void print() //建议也把virtual写上
//void print()
{
cout<<"This is B"<<endl;
}
};
/*
int main()
{
//main1
A a;
B b;
//这两个class因个体的差异而采用了不同的策略
//这并不是多态性行为,多态性行为使用的是不同类型的指针,这里没有用到虚函数的功能。
a.print();
b.print();
//输出:
// This is A
//This is B
return 0;
}
*/
int main()
{
//main2
A a;
B b;
//在A中print()不是虚函数定义时,则返回A的指针引用,输出:
//This is A
//This is A
//在A中print()是虚函数定义时(virtual void print()),则返回各自的指针引用,输出:
//This is A
//This is B
A *p1 = &a;
A *p2 = &b;
p1->print();
p2->print();
return 0;
}
例(Java):
注意:
/**
* 一个.java文件可以有多个类,但只能有一个public的类,并且public的类名必须与文件名相一致。
* 编译器在编译时,针对一个java源代码文件(也称为“编译单元”)只会接受一个public类。否则报错。
* public类不是必须的,java文件中可以没有public类。
* 为什么这个public的类的类名必须和文件名相同:是为了方便虚拟机在相应的路径中找到相应的类所对应的字节码文件
*/
/**
* instanceof 严格来说是Java中的一个双目运算符,用来测试一个对象是否为一个类的实例,用法为:
* boolean result = obj instanceof Class
* 其中 obj 为一个对象,Class 表示一个类或者一个接口,
* 当 obj 为 Class 的对象,或者是其直接或间接子类,或者是其接口的实现类,结果result 都返回 true,否则返回false。
*/
/**
* 一个.java文件可以有多个类,但只能有一个public的类,并且public的类名必须与文件名相一致。
* 编译器在编译时,针对一个java源代码文件(也称为“编译单元”)只会接受一个public类。否则报错。
* public类不是必须的,java文件中可以没有public类。
* 为什么这个public的类的类名必须和文件名相同:是为了方便虚拟机在相应的路径中找到相应的类所对应的字节码文件
*/
class Person {
public void eat() {
System.out.println("吃");
}
public void drink() {
System.out.println("喝");
}
}
class Man extends Person {
//重写:
@Override
public void eat() {
System.out.println("吃肉");
}
@Override
public void drink() {
System.out.println("喝酒");
}
public void smoking() {
System.out.println("抽烟");
}
}
class Woman extends Person {
@Override
public void eat() {
System.out.println("吃水果");
}
@Override
public void drink() {
System.out.println("珍珠奶茶");
}
public void shopping() {
System.out.println("买东西");
}
}
//多态:
public class Test {
public void show(Person person){
person.eat();
person.drink();
/**
* instanceof 严格来说是Java中的一个双目运算符,用来测试一个对象是否为一个类的实例,用法为:
* boolean result = obj instanceof Class
* 其中 obj 为一个对象,Class 表示一个类或者一个接口,
* 当 obj 为 Class 的对象,或者是其直接或间接子类,或者是其接口的实现类,结果result 都返回 true,否则返回false。
*/
if(person instanceof Man){
Man man=(Man)person;
man.smoking();
}else if(person instanceof Woman){
Woman woman=(Woman)person;
woman.shopping();
}
}
public static void main(String[] args) {
Test test=new Test();
test.show(new Person());
test.show(new Man());
test.show(new Woman());
}
}
结果:
吃
喝
吃肉
喝酒
抽烟
吃水果
珍珠奶茶
买东西
封装:解决了数据的安全性问题。
继承:解决了代码的重用问题。
多态:解决了程序的扩展问题。
10、重写(overwrite) 和 重载(overload):
区别点 重载方法 重写方法
参数列表 必须修改 一定不能修改
返回类型 可以修改 一定不能修改
异常 可以修改 可以减少或删除,一定不能抛出新的或者更广的异常
访问 可以修改 一定不能做更严格的限制(可以降低限制)
方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。
(1)方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overloading)。
(2)方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Overriding)。
(3)方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。
11、数据结构:
//数据结构(栈):
Stack stack = new Stack();
//入栈,压栈
stack.push("张三");
stack.push("李四");
stack.push("王五");
System.out.println(stack);
//出栈
stack.pop();
System.out.println(stack);
//获取当前栈栈顶的一个元素
stack.peek();
System.out.println(stack.peek());
//判断当前栈是否为空
stack.empty();
System.out.println(stack);
System.out.println(stack.empty());
//清空栈
stack.clear();
System.out.println(stack);
结果:
[张三, 李四, 王五]
[张三, 李四]
李四
[张三, 李四]
false
[]