一、Java数组定义与C++数组定义区别二、内存分配三、形参实参四、String、StringBuffer和StringBulider五、重写和重载
一、Java数组定义与C++数组定义区别
之前用 C++ 的时候都是直接写type Arr[x]或type *Arr = new type[x]
而 Java 有两种不同的写法:
type[] arr 定义了type类型的数组,名称为arr
type arr[] (非首选) 定义了type类型的变量,变量名为arr数组
其中动态初始化和静态初始化分别为:
动态初始化: type[] arr = new type[x];
静态初始化: type[] arr ={…};
看到教程又联想起408的知识点了,就详细写一下好了:
以C语言为例:C语言编写程序时一般分三个段,它们一般是正文段(即代码和赋值数据段)、数据堆段和数据栈段。二进制代码和常量放在正文段,动态分配存储区在数据堆段,临时使用的变量在数据栈段,而进程的优先级存储在PCB内。
这段内容我是用“堆存栈临”的口诀记住的。
而在Java中,数组的内存分配也类似于上述情况:
1、堆:存放new(对象)。
2、栈:存放局部变量。
3、数据段:存放类变量、常量。
4、代码段:存放方法的定义。
而多个数组的情况下,若定义两数组相同,则指向相同:
而数组在内存中是否连续这个问题,引用自参考资料:
https://blog.csdn.net/MC_007/article/details/106411034
用栈声明的时候很明显,都是连续的。
在堆上的时候,由于是分批次分配内存(首先new出或malloc多少行,然后每一行再分别new),因此其存放是平行的几条连续存储,每一行是连续的,行与行之间并不连续。
三、形参实参
节选自:https://blog.csdn.net/weixin_42738587/article/details/89100872
形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量。
实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值。
public class Test {
public static int add(int a,int b){//a和b为形参
return a+b;
}
public static void main(String[] args) {
int A = 1,B = 2;
System.out.println(add(A,B));//A和B为实参
}
}
四、String、StringBuffer和StringBulider
这里引用自菜鸟教程和https://www.cnblogs.com/weibanggang/p/9455926.html
首先记一下String的简单操作:
连接字符串:
1.string1.concat(string2);
2.“webstie:”.concat(“Runoob”);
3.“Hello,” + " runoob" + “!”
三者共同之处:都是final类,不允许被继承,主要是从性能和安全性上考虑的,因为这几个类都是经常被使用着,且考虑到防止其中的参数被参数修改影响到其他的应用。
StringBuffer是线程安全,可以不需要额外的同步用于多线程中;
StringBuilder是非同步,运行于多线程中就需要使用着单独同步处理,但是速度就比StringBuffer快多了;
StringBuffer与StringBuilder两者共同之处:可以通过append、indert进行字符串的操作。
String实现了三个接口:Serializable、Comparable、CarSequence
StringBuilder只实现了两个接口Serializable、CharSequence,相比之下String的实例可以通过compareTo方法进行比较,其他两个不可以。
public class RunoobTest{
public static void main(String args[]){
StringBuilder sb = new StringBuilder(10); //数组长度为10的String
sb.append("Runoob.."); //添加
System.out.println(sb);
sb.append("!");
System.out.println(sb);
sb.insert(8, "Java");//在第8位加入Java,数组总长度同时改变
System.out.println(sb);
sb.delete(5,8);//删除第5位到第8位 数组总长度不变
sb.replace(int start, int end, String str) //替换
System.out.println(sb);
}
}
运行速度方面:StringBuilder > StringBuffer > String
原因:String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String对象一旦创建之后该对象是不可更改的,但后两者的对象是变量,是可以更改的。
线程安全方面:StringBuilder是线程不安全的,而StringBuffer是线程安全的
如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized(同步)关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。所以如果要进行的操作是多线程的,那么就要使用StringBuffer,但是在单线程的情况下,还是建议使用速度比较快的StringBuilder。
总结:
String:适用于少量的字符串操作的情况
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况
五、重写和重载
先简述一下重写与重载的区别:
重写(Overriding): 父类与子类之间的多态性,对父类的函数进行重新定义
重载(Overloading): 统一的方式处理不同类型数据的一种手段,在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。
//重构
class Animal{
public void move(){
System.out.println("动物可以移动");
}
}
class Dog extends Animal{
public void move(){
System.out.println("狗可以跑和走");
}
}
public class TestDog{
public static void main(String args[]){
Animal a = new Animal(); // Animal 对象
Animal b = new Dog(); // Dog 对象
a.move();// 执行 Animal 类的方法
b.move();//执行 Dog 类的方法
}
}
//重载
public class Overloading {
public int test(){
System.out.println("test1");
return 1;
}
public void test(int a){
System.out.println("test2");
}
//以下两个参数类型顺序不同
public String test(int a,String s){
System.out.println("test3");
return "returntest3";
}
public String test(String s,int a){
System.out.println("test4");
return "returntest4";
}
public static void main(String[] args){
Overloading o = new Overloading();
System.out.println(o.test());
o.test(1);
System.out.println(o.test(1,"test3"));
System.out.println(o.test("test4",1));
}
}



