{"record":{"id":"243f107f71c82214","repo":"Blankj/AndroidUtilCode","slug":"set-circle-needn-t-set-radius","errorCode":null,"errorMessage":"Set circle needn't set radius.","messagePattern":"Set circle needn't set radius\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"lib/utilcode/src/main/java/com/blankj/utilcode/util/ShadowUtils.java","lineNumber":78,"sourceCode":"        private static final int SHADOW_COLOR_DEFAULT = 0x44000000;\n        private static final int SHADOW_SIZE          = UtilsBridge.dp2px(8);\n\n        private float   mShadowRadius         = -1;\n        private float   mShadowSizeNormal     = -1;\n        private float   mShadowSizePressed    = -1;\n        private float   mShadowMaxSizeNormal  = -1;\n        private float   mShadowMaxSizePressed = -1;\n        private int     mShadowColorNormal    = SHADOW_COLOR_DEFAULT;\n        private int     mShadowColorPressed   = SHADOW_COLOR_DEFAULT;\n        private boolean isCircle              = false;\n\n        public Config() {\n        }\n\n        public Config setShadowRadius(float radius) {\n            this.mShadowRadius = radius;\n            if (isCircle) {\n                throw new IllegalArgumentException(\"Set circle needn't set radius.\");\n            }\n            return this;\n        }\n\n        public Config setCircle() {\n            isCircle = true;\n            if (mShadowRadius != -1) {\n                throw new IllegalArgumentException(\"Set circle needn't set radius.\");\n            }\n            return this;\n        }\n\n        public Config setShadowSize(int size) {\n            return setShadowSize(size, size);\n        }\n\n        public Config setShadowSize(int sizeNormal, int sizePressed) {\n            this.mShadowSizeNormal = sizeNormal;","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/Blankj/AndroidUtilCode/blob/7b4caf9e5440046b3fefb63b6b6e2ead7ebaf809/lib/utilcode/src/main/java/com/blankj/utilcode/util/ShadowUtils.java#L60-L96","documentation":"ShadowUtils.Config.setShadowRadius stores the radius and then throws IllegalArgumentException if isCircle is already true. The builder enforces a mutual-exclusion contract: a circular shadow has no meaningful radius, so once setCircle() has been called, supplying a radius is a configuration error. The throw happens AFTER the field is written, signalling the caller violated the intended build order.","triggerScenarios":"Calling new ShadowUtils.Config().setCircle().setShadowRadius(x) — the radius call throws because isCircle is already true. Any build sequence where setCircle() precedes setShadowRadius() triggers it.","commonSituations":"Copy-pasting config code that chained setShadowRadius for a rectangular shadow and then flipping to setCircle; conditional builder logic that sets radius in one branch and circle in another; refactor where setCircle was added late without removing the radius call.","solutions":["Remove the setShadowRadius call from any builder chain that also calls setCircle — circle shadows derive radius from size, not an explicit radius.","If you need both shapes, build two separate Config instances rather than toggling on one.","Reorder logic so setCircle() is chosen instead of setShadowRadius(), never both.","Audit the build chain end-to-end before apply() to ensure only one of the two is set."],"exampleFix":"// before\nnew ShadowUtils.Config()\n    .setCircle()\n    .setShadowRadius(8)   // throws\n    ...\n\n// after\nnew ShadowUtils.Config()\n    .setCircle()\n    .setShadowSize(8)\n    ...","handlingStrategy":"validation","validationCode":"// Validate build intent before constructing the Config chain.\nboolean useCircle = /* ... */;\nif (useCircle) {\n  // do NOT call setShadowRadius; use setShadowSize only\n} else {\n  // call setShadowRadius, do NOT call setCircle\n}","typeGuard":null,"tryCatchPattern":"try {\n  config.setShadowRadius(r);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"circle\")) { /* radius not valid for circle; ignore or log */ }\n  else throw e;\n}","preventionTips":["Decide circle vs rectangular shadow before building the Config.","Never chain both setCircle and setShadowRadius on the same Config.","Centralize shadow Config construction in one factory method per shape.","Add a unit test covering each shape variant."],"tags":["android","shadow","builder","validation","config"],"backgroundTag":null,"analyzedSha":"7b4caf9e5440046b3fefb63b6b6e2ead7ebaf809","analyzedAt":"2026-08-14T02:26:54.956Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}