在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 問答/Java/ java不是值傳遞嗎?為什么會出現(xiàn)這種情況

java不是值傳遞嗎?為什么會出現(xiàn)這種情況

如題,按說java是值傳遞的,可下面的代碼能正確運行,getClassSet方法中有一個局部的set變量,在doAddClass方法里對其進行了add但沒有返回,但最后卻能從getClassSet方法返回的set里獲取到元素,這是為什么?代碼略長,勞煩大佬了

/**
     * 獲取指定包名下的所有類文件,可讀取class或jar
     * Enumeration古代迭代器
     */
    public static Set<Class<?>> getClassSet(String packageName) {
        Set<Class<?>> classes = new HashSet<>();
        try {
            //獲取文件系統(tǒng)下的資源文件,url路徑類似 file:/C:/Users/Kaibo/OneDrive/workplaceForIDEA/SmartFramework/target/classes/com/smar4j/framework/util
            Enumeration<URL> urls = getClassLoader().getResources(packageName.replace(".", "/"));
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                if (null != url) {
                    String protocol = url.getProtocol();
                    //判斷url協(xié)議,file還是jar
                    if ("file".equals(protocol)) {
                        //替換url中的空格
                        String packagePath = url.getPath().replaceAll("%20", "");
                        addClass(classes, packagePath, packageName);
                    } else if ("jar".equals(protocol)) {
                        //操作jar文件
                        JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
                        if (null != jarURLConnection) {
                            JarFile jarFile = jarURLConnection.getJarFile();
                            if (null != jarFile) {
                                Enumeration<JarEntry> entries = jarFile.entries();
                                while (entries.hasMoreElements()) {
                                    JarEntry jarEntry = entries.nextElement();
                                    String name = jarEntry.getName();
                                    if (name.endsWith(".class")) {
                                        String className = name.substring(0, name.lastIndexOf(".")).replaceAll("/", ".");
                                        doAddClass(classes, className);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return classes;
    }

    private static void addClass(Set<Class<?>> classes, String packagePath, String packageName) {
        File[] files = new File(packagePath).listFiles(new FileFilter() {
            @Override
            public boolean accept(File file) {
                return (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory();
            }
        });
        for (File file : files) {
            String fileName = file.getName();
            //如果不是目錄
            if (file.isFile()) {
                String className = fileName.substring(0, fileName.lastIndexOf("."));
                if (StringUtil.isNotEmpty(packageName)) {
                    className = packageName + "." + className;
                    doAddClass(classes, className);
                } else {
                    String subPackagePath = fileName;
                    if (StringUtil.isNotEmpty(packagePath)) {
                        subPackagePath = packagePath + "/" + subPackagePath;
                    }
                    String subPackageName = fileName;
                    if (StringUtil.isNotEmpty(packageName)) {
                        subPackageName = packageName + "." + subPackageName;
                    }
                    addClass(classes, subPackagePath, subPackageName);
                }
            }
        }
    }
    private static void doAddClass(Set<Class<?>> classes, String className) {
        Class<?> cls = loadClass(className, false);
        classes.add(cls);
    }
回答
編輯回答
囍槑

HashSet源碼是基于HashMap實現(xiàn)的

public class HashSet<E>
    extends AbstractSet<E>
    implements Set<E>, Cloneable, java.io.Serializable
{
    static final long serialVersionUID = -5024744406713321676L;

    private transient HashMap<E,Object> map;
 Set<Class<?>> classes = new HashSet<>();
調(diào)用private static void doAddClass(Set<Class<?>> classes, String className)方法 

兩個classes引用同時指向new HashSet<>()這個對象,在方法里面執(zhí)行 classes.add(cls);
也就是調(diào)用了map的put方法,修改了這個共同指向?qū)ο罄锩娴腍ashMap成員變量的內(nèi)容,返回的也是這個對象,所以getClassSet方法返回的set里能獲取到元素。

2017年11月3日 05:36
編輯回答
慢半拍

值傳遞沒錯, 但相對于簡單類型是這樣, 對于類來說,值是類的內(nèi)存地址, 也就是引用. 如果你改了引用對應(yīng)對象的內(nèi)部值, 也沒有誰能攔得了你. 網(wǎng)上資料太多, 不重復了.

打個比方說, 集合類型就是書包, 你背上書包進了樓, 相當于是調(diào)用了進樓方法, 執(zhí)行完成了,你出了樓, 你沒有變, 書包也沒有變. 但你書包里的東西變沒變就不好說了.

2018年6月11日 16:01
編輯回答
乖乖噠

大佬們都把技術(shù)問題說了,不過我還是推薦你看一本書,鮑勃大叔的 《clean code》

2018年8月31日 04:43
編輯回答
喜歡你

對于對象來說,傳遞的只是引用,不是以副本形式(值)傳遞的,8 種基本類型(非對應(yīng)的類類型)才是傳值。

2017年11月3日 10:16
編輯回答
安于心

這種也叫引用傳遞,傳遞的是對象的內(nèi)存地址。也就是說這兩個方法里的變量指向的是同一塊內(nèi)存地址。

classes.add(cls);對內(nèi)存地址里的數(shù)據(jù)做了修改,也直接反應(yīng)到getClassSet里的變量,因為它們是同一個對象

2018年1月3日 20:56